From 465dc1b2ebc073c0071fcc025e782a858b92499b Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Wed, 30 Oct 2024 15:17:16 -0400 Subject: [PATCH] Improve the Parser's API and Storage of Metadata (#3003) --- cpp/src/Slice/Grammar.cpp | 254 +++++----- cpp/src/Slice/Grammar.y | 90 ++-- cpp/src/Slice/GrammarUtil.h | 6 +- cpp/src/Slice/Parser.cpp | 320 +++++++----- cpp/src/Slice/Parser.h | 133 +++-- cpp/src/Slice/Scanner.cpp | 101 ++-- cpp/src/Slice/Scanner.l | 4 +- cpp/src/ice2slice/Gen.cpp | 22 +- cpp/src/slice2cpp/CPlusPlusUtil.cpp | 131 ++--- cpp/src/slice2cpp/CPlusPlusUtil.h | 8 +- cpp/src/slice2cpp/Gen.cpp | 259 +++++----- cpp/src/slice2cpp/Gen.h | 2 +- cpp/src/slice2cpp/Main.cpp | 7 +- cpp/src/slice2cs/CsUtil.cpp | 144 ++---- cpp/src/slice2cs/Gen.cpp | 86 ++-- cpp/src/slice2java/Gen.cpp | 55 +- cpp/src/slice2java/JavaUtil.cpp | 473 ++++++++---------- cpp/src/slice2java/JavaUtil.h | 25 +- cpp/src/slice2js/Gen.cpp | 19 +- cpp/src/slice2js/JsUtil.cpp | 6 +- cpp/src/slice2py/PythonUtil.cpp | 155 +++--- cpp/src/slice2swift/Gen.cpp | 28 +- cpp/src/slice2swift/SwiftUtil.cpp | 139 ++--- cpp/src/slice2swift/SwiftUtil.h | 7 +- .../errorDetection/WarningInvalidMetadata.err | 42 +- 25 files changed, 1189 insertions(+), 1327 deletions(-) diff --git a/cpp/src/Slice/Grammar.cpp b/cpp/src/Slice/Grammar.cpp index 1a69fe43a48..eefd8f5ef92 100644 --- a/cpp/src/Slice/Grammar.cpp +++ b/cpp/src/Slice/Grammar.cpp @@ -320,7 +320,7 @@ enum yysymbol_kind_t YYSYMBOL_builtin = 124, /* builtin */ YYSYMBOL_type = 125, /* type */ YYSYMBOL_string_literal = 126, /* string_literal */ - YYSYMBOL_string_list = 127, /* string_list */ + YYSYMBOL_metadata_list = 127, /* metadata_list */ YYSYMBOL_const_initializer = 128, /* const_initializer */ YYSYMBOL_const_def = 129, /* const_def */ YYSYMBOL_keyword = 130 /* keyword */ @@ -742,11 +742,11 @@ static const yytype_int16 yyrline[] = 1671, 1680, 1686, 1704, 1716, 1720, 1761, 1767, 1778, 1781, 1797, 1813, 1825, 1837, 1848, 1864, 1868, 1877, 1880, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1902, - 1906, 1911, 1942, 1978, 1984, 1992, 1999, 2011, 2020, 2029, - 2064, 2071, 2078, 2090, 2099, 2113, 2114, 2115, 2116, 2117, - 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, - 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, - 2138, 2139 + 1906, 1911, 1942, 1978, 1984, 1992, 2002, 2017, 2026, 2035, + 2070, 2077, 2084, 2096, 2105, 2119, 2120, 2121, 2122, 2123, + 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, + 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, + 2144, 2145 }; #endif @@ -787,7 +787,7 @@ static const char *const yytname[] = "sequence_def", "dictionary_def", "enum_id", "enum_def", "@22", "@23", "enumerator_list", "enumerator", "enumerator_initializer", "out_qualifier", "parameters", "throws", "scoped_name", "builtin", - "type", "string_literal", "string_list", "const_initializer", + "type", "string_literal", "metadata_list", "const_initializer", "const_def", "keyword", YY_NULLPTR }; @@ -1748,7 +1748,7 @@ YYLTYPE yylloc = yyloc_default; #line 1749 "src/Slice/Grammar.cpp" break; - case 5: /* file_metadata: ICE_FILE_METADATA_OPEN string_list ICE_FILE_METADATA_CLOSE */ + case 5: /* file_metadata: ICE_FILE_METADATA_OPEN metadata_list ICE_FILE_METADATA_CLOSE */ #line 202 "src/Slice/Grammar.y" { yyval = yyvsp[-1]; @@ -1756,7 +1756,7 @@ YYLTYPE yylloc = yyloc_default; #line 1757 "src/Slice/Grammar.cpp" break; - case 6: /* metadata: ICE_METADATA_OPEN string_list ICE_METADATA_CLOSE */ + case 6: /* metadata: ICE_METADATA_OPEN metadata_list ICE_METADATA_CLOSE */ #line 211 "src/Slice/Grammar.y" { yyval = yyvsp[-1]; @@ -1767,7 +1767,7 @@ YYLTYPE yylloc = yyloc_default; case 7: /* metadata: %empty */ #line 215 "src/Slice/Grammar.y" { - yyval = make_shared(); + yyval = make_shared(); } #line 1773 "src/Slice/Grammar.cpp" break; @@ -1775,10 +1775,10 @@ YYLTYPE yylloc = yyloc_default; case 8: /* definitions: definitions file_metadata */ #line 224 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[0]); + auto metadata = dynamic_pointer_cast(yyvsp[0]); if (!metadata->v.empty()) { - currentUnit->addFileMetadata(metadata->v); + currentUnit->addFileMetadata(std::move(metadata->v)); } } #line 1785 "src/Slice/Grammar.cpp" @@ -1787,11 +1787,11 @@ YYLTYPE yylloc = yyloc_default; case 9: /* definitions: definitions metadata definition */ #line 232 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[-1]); + auto metadata = dynamic_pointer_cast(yyvsp[-1]); auto contained = dynamic_pointer_cast(yyvsp[0]); if (contained && !metadata->v.empty()) { - contained->setMetadata(metadata->v); + contained->setMetadata(std::move(metadata->v)); } } #line 1798 "src/Slice/Grammar.cpp" @@ -2668,11 +2668,11 @@ YYLTYPE yylloc = yyloc_default; case 80: /* data_members: metadata data_member ';' data_members */ #line 989 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[-3]); + auto metadata = dynamic_pointer_cast(yyvsp[-3]); auto contained = dynamic_pointer_cast(yyvsp[-2]); if (contained && !metadata->v.empty()) { - contained->setMetadata(metadata->v); + contained->setMetadata(std::move(metadata->v)); } } #line 2679 "src/Slice/Grammar.cpp" @@ -3219,11 +3219,11 @@ YYLTYPE yylloc = yyloc_default; case 110: /* operations: metadata operation ';' operations */ #line 1470 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[-3]); + auto metadata = dynamic_pointer_cast(yyvsp[-3]); auto contained = dynamic_pointer_cast(yyvsp[-2]); if (contained && !metadata->v.empty()) { - contained->setMetadata(metadata->v); + contained->setMetadata(std::move(metadata->v)); } } #line 3230 "src/Slice/Grammar.cpp" @@ -3303,10 +3303,10 @@ YYLTYPE yylloc = yyloc_default; #line 1536 "src/Slice/Grammar.y" { auto ident = dynamic_pointer_cast(yyvsp[0]); - auto metadata = dynamic_pointer_cast(yyvsp[-3]); + auto metadata = dynamic_pointer_cast(yyvsp[-3]); auto type = dynamic_pointer_cast(yyvsp[-2]); ContainerPtr cont = currentUnit->currentContainer(); - yyval = cont->createSequence(ident->v, type, metadata->v); + yyval = cont->createSequence(ident->v, type, std::move(metadata->v)); } #line 3312 "src/Slice/Grammar.cpp" break; @@ -3315,10 +3315,10 @@ YYLTYPE yylloc = yyloc_default; #line 1544 "src/Slice/Grammar.y" { auto ident = dynamic_pointer_cast(yyvsp[0]); - auto metadata = dynamic_pointer_cast(yyvsp[-3]); + auto metadata = dynamic_pointer_cast(yyvsp[-3]); auto type = dynamic_pointer_cast(yyvsp[-2]); ContainerPtr cont = currentUnit->currentContainer(); - yyval = cont->createSequence(ident->v, type, metadata->v); // Dummy + yyval = cont->createSequence(ident->v, type, std::move(metadata->v)); // Dummy currentUnit->error("keyword `" + ident->v + "' cannot be used as sequence name"); } #line 3325 "src/Slice/Grammar.cpp" @@ -3328,12 +3328,12 @@ YYLTYPE yylloc = yyloc_default; #line 1558 "src/Slice/Grammar.y" { auto ident = dynamic_pointer_cast(yyvsp[0]); - auto keyMetadata = dynamic_pointer_cast(yyvsp[-6]); + auto keyMetadata = dynamic_pointer_cast(yyvsp[-6]); auto keyType = dynamic_pointer_cast(yyvsp[-5]); - auto valueMetadata = dynamic_pointer_cast(yyvsp[-3]); + auto valueMetadata = dynamic_pointer_cast(yyvsp[-3]); auto valueType = dynamic_pointer_cast(yyvsp[-2]); ContainerPtr cont = currentUnit->currentContainer(); - yyval = cont->createDictionary(ident->v, keyType, keyMetadata->v, valueType, valueMetadata->v); + yyval = cont->createDictionary(ident->v, keyType, std::move(keyMetadata->v), valueType, std::move(valueMetadata->v)); } #line 3339 "src/Slice/Grammar.cpp" break; @@ -3342,12 +3342,12 @@ YYLTYPE yylloc = yyloc_default; #line 1568 "src/Slice/Grammar.y" { auto ident = dynamic_pointer_cast(yyvsp[0]); - auto keyMetadata = dynamic_pointer_cast(yyvsp[-6]); + auto keyMetadata = dynamic_pointer_cast(yyvsp[-6]); auto keyType = dynamic_pointer_cast(yyvsp[-5]); - auto valueMetadata = dynamic_pointer_cast(yyvsp[-3]); + auto valueMetadata = dynamic_pointer_cast(yyvsp[-3]); auto valueType = dynamic_pointer_cast(yyvsp[-2]); ContainerPtr cont = currentUnit->currentContainer(); - yyval = cont->createDictionary(ident->v, keyType, keyMetadata->v, valueType, valueMetadata->v); // Dummy + yyval = cont->createDictionary(ident->v, keyType, std::move(keyMetadata->v), valueType, std::move(valueMetadata->v)); // Dummy currentUnit->error("keyword `" + ident->v + "' cannot be used as dictionary name"); } #line 3354 "src/Slice/Grammar.cpp" @@ -3433,11 +3433,11 @@ YYLTYPE yylloc = yyloc_default; case 128: /* enumerator_list: metadata enumerator ',' enumerator_list */ #line 1648 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[-3]); + auto metadata = dynamic_pointer_cast(yyvsp[-3]); auto enumerator = dynamic_pointer_cast(yyvsp[-2]); if (enumerator && !metadata->v.empty()) { - enumerator->setMetadata(metadata->v); + enumerator->setMetadata(std::move(metadata->v)); } auto enumeratorList = dynamic_pointer_cast(yyvsp[0]); enumeratorList->v.push_front(enumerator); @@ -3449,11 +3449,11 @@ YYLTYPE yylloc = yyloc_default; case 129: /* enumerator_list: metadata enumerator */ #line 1660 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[-1]); + auto metadata = dynamic_pointer_cast(yyvsp[-1]); auto enumerator = dynamic_pointer_cast(yyvsp[0]); if (enumerator && !metadata->v.empty()) { - enumerator->setMetadata(metadata->v); + enumerator->setMetadata(std::move(metadata->v)); } auto enumeratorList = make_shared(); enumeratorList->v.push_front(enumerator); @@ -3598,10 +3598,10 @@ YYLTYPE yylloc = yyloc_default; { ParamDeclPtr pd = op->createParamDecl(tsp->name, tsp->type, isOutParam->v, tsp->isOptional, tsp->tag); currentUnit->currentContainer()->checkIntroduced(tsp->name, pd); - auto metadata = dynamic_pointer_cast(yyvsp[-1]); + auto metadata = dynamic_pointer_cast(yyvsp[-1]); if (!metadata->v.empty()) { - pd->setMetadata(metadata->v); + pd->setMetadata(std::move(metadata->v)); } } } @@ -3618,10 +3618,10 @@ YYLTYPE yylloc = yyloc_default; { ParamDeclPtr pd = op->createParamDecl(tsp->name, tsp->type, isOutParam->v, tsp->isOptional, tsp->tag); currentUnit->currentContainer()->checkIntroduced(tsp->name, pd); - auto metadata = dynamic_pointer_cast(yyvsp[-1]); + auto metadata = dynamic_pointer_cast(yyvsp[-1]); if (!metadata->v.empty()) { - pd->setMetadata(metadata->v); + pd->setMetadata(std::move(metadata->v)); } } } @@ -3884,30 +3884,36 @@ YYLTYPE yylloc = yyloc_default; #line 3885 "src/Slice/Grammar.cpp" break; - case 165: /* string_list: string_list ',' string_literal */ + case 165: /* metadata_list: metadata_list ',' string_literal */ #line 1993 "src/Slice/Grammar.y" { auto str = dynamic_pointer_cast(yyvsp[0]); - auto stringList = dynamic_pointer_cast(yyvsp[-2]); - stringList->v.push_back(str->v); - yyval = stringList; + auto metadataList = dynamic_pointer_cast(yyvsp[-2]); + + auto metadata = make_shared(str->v, currentUnit->currentFile(), currentUnit->currentLine()); + metadataList->v.push_back(metadata); + + yyval = metadataList; } -#line 3896 "src/Slice/Grammar.cpp" +#line 3899 "src/Slice/Grammar.cpp" break; - case 166: /* string_list: string_literal */ -#line 2000 "src/Slice/Grammar.y" + case 166: /* metadata_list: string_literal */ +#line 2003 "src/Slice/Grammar.y" { auto str = dynamic_pointer_cast(yyvsp[0]); - auto stringList = make_shared(); - stringList->v.push_back(str->v); - yyval = stringList; + auto metadataList = make_shared(); + + auto metadata = make_shared(str->v, currentUnit->currentFile(), currentUnit->currentLine()); + metadataList->v.push_back(metadata); + + yyval = metadataList; } -#line 3907 "src/Slice/Grammar.cpp" +#line 3913 "src/Slice/Grammar.cpp" break; case 167: /* const_initializer: ICE_INTEGER_LITERAL */ -#line 2012 "src/Slice/Grammar.y" +#line 2018 "src/Slice/Grammar.y" { BuiltinPtr type = currentUnit->createBuiltin(Builtin::KindLong); auto intVal = dynamic_pointer_cast(yyvsp[0]); @@ -3916,11 +3922,11 @@ YYLTYPE yylloc = yyloc_default; auto def = make_shared(type, sstr.str()); yyval = def; } -#line 3920 "src/Slice/Grammar.cpp" +#line 3926 "src/Slice/Grammar.cpp" break; case 168: /* const_initializer: ICE_FLOATING_POINT_LITERAL */ -#line 2021 "src/Slice/Grammar.y" +#line 2027 "src/Slice/Grammar.y" { BuiltinPtr type = currentUnit->createBuiltin(Builtin::KindDouble); auto floatVal = dynamic_pointer_cast(yyvsp[0]); @@ -3929,11 +3935,11 @@ YYLTYPE yylloc = yyloc_default; auto def = make_shared(type, sstr.str()); yyval = def; } -#line 3933 "src/Slice/Grammar.cpp" +#line 3939 "src/Slice/Grammar.cpp" break; case 169: /* const_initializer: scoped_name */ -#line 2030 "src/Slice/Grammar.y" +#line 2036 "src/Slice/Grammar.y" { auto scoped = dynamic_pointer_cast(yyvsp[0]); ConstDefTokPtr def; @@ -3968,232 +3974,232 @@ YYLTYPE yylloc = yyloc_default; } yyval = def; } -#line 3972 "src/Slice/Grammar.cpp" +#line 3978 "src/Slice/Grammar.cpp" break; case 170: /* const_initializer: ICE_STRING_LITERAL */ -#line 2065 "src/Slice/Grammar.y" +#line 2071 "src/Slice/Grammar.y" { BuiltinPtr type = currentUnit->createBuiltin(Builtin::KindString); auto literal = dynamic_pointer_cast(yyvsp[0]); auto def = make_shared(type, literal->v); yyval = def; } -#line 3983 "src/Slice/Grammar.cpp" +#line 3989 "src/Slice/Grammar.cpp" break; case 171: /* const_initializer: ICE_FALSE */ -#line 2072 "src/Slice/Grammar.y" +#line 2078 "src/Slice/Grammar.y" { BuiltinPtr type = currentUnit->createBuiltin(Builtin::KindBool); auto literal = dynamic_pointer_cast(yyvsp[0]); auto def = make_shared(type, "false"); yyval = def; } -#line 3994 "src/Slice/Grammar.cpp" +#line 4000 "src/Slice/Grammar.cpp" break; case 172: /* const_initializer: ICE_TRUE */ -#line 2079 "src/Slice/Grammar.y" +#line 2085 "src/Slice/Grammar.y" { BuiltinPtr type = currentUnit->createBuiltin(Builtin::KindBool); auto literal = dynamic_pointer_cast(yyvsp[0]); auto def = make_shared(type, "true"); yyval = def; } -#line 4005 "src/Slice/Grammar.cpp" +#line 4011 "src/Slice/Grammar.cpp" break; case 173: /* const_def: ICE_CONST metadata type ICE_IDENTIFIER '=' const_initializer */ -#line 2091 "src/Slice/Grammar.y" +#line 2097 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[-4]); + auto metadata = dynamic_pointer_cast(yyvsp[-4]); auto const_type = dynamic_pointer_cast(yyvsp[-3]); auto ident = dynamic_pointer_cast(yyvsp[-2]); auto value = dynamic_pointer_cast(yyvsp[0]); - yyval = currentUnit->currentContainer()->createConst(ident->v, const_type, metadata->v, value->v, + yyval = currentUnit->currentContainer()->createConst(ident->v, const_type, std::move(metadata->v), value->v, value->valueAsString); } -#line 4018 "src/Slice/Grammar.cpp" +#line 4024 "src/Slice/Grammar.cpp" break; case 174: /* const_def: ICE_CONST metadata type '=' const_initializer */ -#line 2100 "src/Slice/Grammar.y" +#line 2106 "src/Slice/Grammar.y" { - auto metadata = dynamic_pointer_cast(yyvsp[-3]); + auto metadata = dynamic_pointer_cast(yyvsp[-3]); auto const_type = dynamic_pointer_cast(yyvsp[-2]); auto value = dynamic_pointer_cast(yyvsp[0]); currentUnit->error("missing constant name"); - yyval = currentUnit->currentContainer()->createConst(Ice::generateUUID(), const_type, metadata->v, value->v, - value->valueAsString, Dummy); // Dummy + yyval = currentUnit->currentContainer()->createConst(Ice::generateUUID(), const_type, std::move(metadata->v), + value->v, value->valueAsString, Dummy); // Dummy } -#line 4031 "src/Slice/Grammar.cpp" +#line 4037 "src/Slice/Grammar.cpp" break; case 175: /* keyword: ICE_MODULE */ -#line 2113 "src/Slice/Grammar.y" +#line 2119 "src/Slice/Grammar.y" {} -#line 4037 "src/Slice/Grammar.cpp" +#line 4043 "src/Slice/Grammar.cpp" break; case 176: /* keyword: ICE_CLASS */ -#line 2114 "src/Slice/Grammar.y" +#line 2120 "src/Slice/Grammar.y" {} -#line 4043 "src/Slice/Grammar.cpp" +#line 4049 "src/Slice/Grammar.cpp" break; case 177: /* keyword: ICE_INTERFACE */ -#line 2115 "src/Slice/Grammar.y" +#line 2121 "src/Slice/Grammar.y" {} -#line 4049 "src/Slice/Grammar.cpp" +#line 4055 "src/Slice/Grammar.cpp" break; case 178: /* keyword: ICE_EXCEPTION */ -#line 2116 "src/Slice/Grammar.y" +#line 2122 "src/Slice/Grammar.y" {} -#line 4055 "src/Slice/Grammar.cpp" +#line 4061 "src/Slice/Grammar.cpp" break; case 179: /* keyword: ICE_STRUCT */ -#line 2117 "src/Slice/Grammar.y" +#line 2123 "src/Slice/Grammar.y" {} -#line 4061 "src/Slice/Grammar.cpp" +#line 4067 "src/Slice/Grammar.cpp" break; case 180: /* keyword: ICE_SEQUENCE */ -#line 2118 "src/Slice/Grammar.y" +#line 2124 "src/Slice/Grammar.y" {} -#line 4067 "src/Slice/Grammar.cpp" +#line 4073 "src/Slice/Grammar.cpp" break; case 181: /* keyword: ICE_DICTIONARY */ -#line 2119 "src/Slice/Grammar.y" +#line 2125 "src/Slice/Grammar.y" {} -#line 4073 "src/Slice/Grammar.cpp" +#line 4079 "src/Slice/Grammar.cpp" break; case 182: /* keyword: ICE_ENUM */ -#line 2120 "src/Slice/Grammar.y" +#line 2126 "src/Slice/Grammar.y" {} -#line 4079 "src/Slice/Grammar.cpp" +#line 4085 "src/Slice/Grammar.cpp" break; case 183: /* keyword: ICE_OUT */ -#line 2121 "src/Slice/Grammar.y" +#line 2127 "src/Slice/Grammar.y" {} -#line 4085 "src/Slice/Grammar.cpp" +#line 4091 "src/Slice/Grammar.cpp" break; case 184: /* keyword: ICE_EXTENDS */ -#line 2122 "src/Slice/Grammar.y" +#line 2128 "src/Slice/Grammar.y" {} -#line 4091 "src/Slice/Grammar.cpp" +#line 4097 "src/Slice/Grammar.cpp" break; case 185: /* keyword: ICE_THROWS */ -#line 2123 "src/Slice/Grammar.y" +#line 2129 "src/Slice/Grammar.y" {} -#line 4097 "src/Slice/Grammar.cpp" +#line 4103 "src/Slice/Grammar.cpp" break; case 186: /* keyword: ICE_VOID */ -#line 2124 "src/Slice/Grammar.y" +#line 2130 "src/Slice/Grammar.y" {} -#line 4103 "src/Slice/Grammar.cpp" +#line 4109 "src/Slice/Grammar.cpp" break; case 187: /* keyword: ICE_BOOL */ -#line 2125 "src/Slice/Grammar.y" +#line 2131 "src/Slice/Grammar.y" {} -#line 4109 "src/Slice/Grammar.cpp" +#line 4115 "src/Slice/Grammar.cpp" break; case 188: /* keyword: ICE_BYTE */ -#line 2126 "src/Slice/Grammar.y" +#line 2132 "src/Slice/Grammar.y" {} -#line 4115 "src/Slice/Grammar.cpp" +#line 4121 "src/Slice/Grammar.cpp" break; case 189: /* keyword: ICE_SHORT */ -#line 2127 "src/Slice/Grammar.y" +#line 2133 "src/Slice/Grammar.y" {} -#line 4121 "src/Slice/Grammar.cpp" +#line 4127 "src/Slice/Grammar.cpp" break; case 190: /* keyword: ICE_INT */ -#line 2128 "src/Slice/Grammar.y" +#line 2134 "src/Slice/Grammar.y" {} -#line 4127 "src/Slice/Grammar.cpp" +#line 4133 "src/Slice/Grammar.cpp" break; case 191: /* keyword: ICE_LONG */ -#line 2129 "src/Slice/Grammar.y" +#line 2135 "src/Slice/Grammar.y" {} -#line 4133 "src/Slice/Grammar.cpp" +#line 4139 "src/Slice/Grammar.cpp" break; case 192: /* keyword: ICE_FLOAT */ -#line 2130 "src/Slice/Grammar.y" +#line 2136 "src/Slice/Grammar.y" {} -#line 4139 "src/Slice/Grammar.cpp" +#line 4145 "src/Slice/Grammar.cpp" break; case 193: /* keyword: ICE_DOUBLE */ -#line 2131 "src/Slice/Grammar.y" +#line 2137 "src/Slice/Grammar.y" {} -#line 4145 "src/Slice/Grammar.cpp" +#line 4151 "src/Slice/Grammar.cpp" break; case 194: /* keyword: ICE_STRING */ -#line 2132 "src/Slice/Grammar.y" +#line 2138 "src/Slice/Grammar.y" {} -#line 4151 "src/Slice/Grammar.cpp" +#line 4157 "src/Slice/Grammar.cpp" break; case 195: /* keyword: ICE_OBJECT */ -#line 2133 "src/Slice/Grammar.y" +#line 2139 "src/Slice/Grammar.y" {} -#line 4157 "src/Slice/Grammar.cpp" +#line 4163 "src/Slice/Grammar.cpp" break; case 196: /* keyword: ICE_CONST */ -#line 2134 "src/Slice/Grammar.y" +#line 2140 "src/Slice/Grammar.y" {} -#line 4163 "src/Slice/Grammar.cpp" +#line 4169 "src/Slice/Grammar.cpp" break; case 197: /* keyword: ICE_FALSE */ -#line 2135 "src/Slice/Grammar.y" +#line 2141 "src/Slice/Grammar.y" {} -#line 4169 "src/Slice/Grammar.cpp" +#line 4175 "src/Slice/Grammar.cpp" break; case 198: /* keyword: ICE_TRUE */ -#line 2136 "src/Slice/Grammar.y" +#line 2142 "src/Slice/Grammar.y" {} -#line 4175 "src/Slice/Grammar.cpp" +#line 4181 "src/Slice/Grammar.cpp" break; case 199: /* keyword: ICE_IDEMPOTENT */ -#line 2137 "src/Slice/Grammar.y" +#line 2143 "src/Slice/Grammar.y" {} -#line 4181 "src/Slice/Grammar.cpp" +#line 4187 "src/Slice/Grammar.cpp" break; case 200: /* keyword: ICE_OPTIONAL */ -#line 2138 "src/Slice/Grammar.y" +#line 2144 "src/Slice/Grammar.y" {} -#line 4187 "src/Slice/Grammar.cpp" +#line 4193 "src/Slice/Grammar.cpp" break; case 201: /* keyword: ICE_VALUE */ -#line 2139 "src/Slice/Grammar.y" +#line 2145 "src/Slice/Grammar.y" {} -#line 4193 "src/Slice/Grammar.cpp" +#line 4199 "src/Slice/Grammar.cpp" break; -#line 4197 "src/Slice/Grammar.cpp" +#line 4203 "src/Slice/Grammar.cpp" default: break; } @@ -4391,5 +4397,5 @@ YYLTYPE yylloc = yyloc_default; return yyresult; } -#line 2142 "src/Slice/Grammar.y" +#line 2148 "src/Slice/Grammar.y" diff --git a/cpp/src/Slice/Grammar.y b/cpp/src/Slice/Grammar.y index e6f714a9c1e..09443781583 100644 --- a/cpp/src/Slice/Grammar.y +++ b/cpp/src/Slice/Grammar.y @@ -198,7 +198,7 @@ opt_semicolon // ---------------------------------------------------------------------- file_metadata // ---------------------------------------------------------------------- -: ICE_FILE_METADATA_OPEN string_list ICE_FILE_METADATA_CLOSE +: ICE_FILE_METADATA_OPEN metadata_list ICE_FILE_METADATA_CLOSE { $$ = $2; } @@ -207,13 +207,13 @@ file_metadata // ---------------------------------------------------------------------- metadata // ---------------------------------------------------------------------- -: ICE_METADATA_OPEN string_list ICE_METADATA_CLOSE +: ICE_METADATA_OPEN metadata_list ICE_METADATA_CLOSE { $$ = $2; } | %empty { - $$ = make_shared(); + $$ = make_shared(); } ; @@ -222,19 +222,19 @@ definitions // ---------------------------------------------------------------------- : definitions file_metadata { - auto metadata = dynamic_pointer_cast($2); + auto metadata = dynamic_pointer_cast($2); if (!metadata->v.empty()) { - currentUnit->addFileMetadata(metadata->v); + currentUnit->addFileMetadata(std::move(metadata->v)); } } | definitions metadata definition { - auto metadata = dynamic_pointer_cast($2); + auto metadata = dynamic_pointer_cast($2); auto contained = dynamic_pointer_cast($3); if (contained && !metadata->v.empty()) { - contained->setMetadata(metadata->v); + contained->setMetadata(std::move(metadata->v)); } } | %empty @@ -987,11 +987,11 @@ data_members // ---------------------------------------------------------------------- : metadata data_member ';' data_members { - auto metadata = dynamic_pointer_cast($1); + auto metadata = dynamic_pointer_cast($1); auto contained = dynamic_pointer_cast($2); if (contained && !metadata->v.empty()) { - contained->setMetadata(metadata->v); + contained->setMetadata(std::move(metadata->v)); } } | error ';' data_members @@ -1468,11 +1468,11 @@ operations // ---------------------------------------------------------------------- : metadata operation ';' operations { - auto metadata = dynamic_pointer_cast($1); + auto metadata = dynamic_pointer_cast($1); auto contained = dynamic_pointer_cast($2); if (contained && !metadata->v.empty()) { - contained->setMetadata(metadata->v); + contained->setMetadata(std::move(metadata->v)); } } | error ';' operations @@ -1535,18 +1535,18 @@ sequence_def : ICE_SEQUENCE '<' metadata type '>' ICE_IDENTIFIER { auto ident = dynamic_pointer_cast($6); - auto metadata = dynamic_pointer_cast($3); + auto metadata = dynamic_pointer_cast($3); auto type = dynamic_pointer_cast($4); ContainerPtr cont = currentUnit->currentContainer(); - $$ = cont->createSequence(ident->v, type, metadata->v); + $$ = cont->createSequence(ident->v, type, std::move(metadata->v)); } | ICE_SEQUENCE '<' metadata type '>' keyword { auto ident = dynamic_pointer_cast($6); - auto metadata = dynamic_pointer_cast($3); + auto metadata = dynamic_pointer_cast($3); auto type = dynamic_pointer_cast($4); ContainerPtr cont = currentUnit->currentContainer(); - $$ = cont->createSequence(ident->v, type, metadata->v); // Dummy + $$ = cont->createSequence(ident->v, type, std::move(metadata->v)); // Dummy currentUnit->error("keyword `" + ident->v + "' cannot be used as sequence name"); } ; @@ -1557,22 +1557,22 @@ dictionary_def : ICE_DICTIONARY '<' metadata type ',' metadata type '>' ICE_IDENTIFIER { auto ident = dynamic_pointer_cast($9); - auto keyMetadata = dynamic_pointer_cast($3); + auto keyMetadata = dynamic_pointer_cast($3); auto keyType = dynamic_pointer_cast($4); - auto valueMetadata = dynamic_pointer_cast($6); + auto valueMetadata = dynamic_pointer_cast($6); auto valueType = dynamic_pointer_cast($7); ContainerPtr cont = currentUnit->currentContainer(); - $$ = cont->createDictionary(ident->v, keyType, keyMetadata->v, valueType, valueMetadata->v); + $$ = cont->createDictionary(ident->v, keyType, std::move(keyMetadata->v), valueType, std::move(valueMetadata->v)); } | ICE_DICTIONARY '<' metadata type ',' metadata type '>' keyword { auto ident = dynamic_pointer_cast($9); - auto keyMetadata = dynamic_pointer_cast($3); + auto keyMetadata = dynamic_pointer_cast($3); auto keyType = dynamic_pointer_cast($4); - auto valueMetadata = dynamic_pointer_cast($6); + auto valueMetadata = dynamic_pointer_cast($6); auto valueType = dynamic_pointer_cast($7); ContainerPtr cont = currentUnit->currentContainer(); - $$ = cont->createDictionary(ident->v, keyType, keyMetadata->v, valueType, valueMetadata->v); // Dummy + $$ = cont->createDictionary(ident->v, keyType, std::move(keyMetadata->v), valueType, std::move(valueMetadata->v)); // Dummy currentUnit->error("keyword `" + ident->v + "' cannot be used as dictionary name"); } ; @@ -1646,11 +1646,11 @@ enumerator_list // ---------------------------------------------------------------------- : metadata enumerator ',' enumerator_list { - auto metadata = dynamic_pointer_cast($1); + auto metadata = dynamic_pointer_cast($1); auto enumerator = dynamic_pointer_cast($2); if (enumerator && !metadata->v.empty()) { - enumerator->setMetadata(metadata->v); + enumerator->setMetadata(std::move(metadata->v)); } auto enumeratorList = dynamic_pointer_cast($4); enumeratorList->v.push_front(enumerator); @@ -1658,11 +1658,11 @@ enumerator_list } | metadata enumerator { - auto metadata = dynamic_pointer_cast($1); + auto metadata = dynamic_pointer_cast($1); auto enumerator = dynamic_pointer_cast($2); if (enumerator && !metadata->v.empty()) { - enumerator->setMetadata(metadata->v); + enumerator->setMetadata(std::move(metadata->v)); } auto enumeratorList = make_shared(); enumeratorList->v.push_front(enumerator); @@ -1787,10 +1787,10 @@ parameters { ParamDeclPtr pd = op->createParamDecl(tsp->name, tsp->type, isOutParam->v, tsp->isOptional, tsp->tag); currentUnit->currentContainer()->checkIntroduced(tsp->name, pd); - auto metadata = dynamic_pointer_cast($2); + auto metadata = dynamic_pointer_cast($2); if (!metadata->v.empty()) { - pd->setMetadata(metadata->v); + pd->setMetadata(std::move(metadata->v)); } } } @@ -1803,10 +1803,10 @@ parameters { ParamDeclPtr pd = op->createParamDecl(tsp->name, tsp->type, isOutParam->v, tsp->isOptional, tsp->tag); currentUnit->currentContainer()->checkIntroduced(tsp->name, pd); - auto metadata = dynamic_pointer_cast($4); + auto metadata = dynamic_pointer_cast($4); if (!metadata->v.empty()) { - pd->setMetadata(metadata->v); + pd->setMetadata(std::move(metadata->v)); } } } @@ -1987,21 +1987,27 @@ string_literal ; // ---------------------------------------------------------------------- -string_list +metadata_list // ---------------------------------------------------------------------- -: string_list ',' string_literal +: metadata_list ',' string_literal { auto str = dynamic_pointer_cast($3); - auto stringList = dynamic_pointer_cast($1); - stringList->v.push_back(str->v); - $$ = stringList; + auto metadataList = dynamic_pointer_cast($1); + + auto metadata = make_shared(str->v, currentUnit->currentFile(), currentUnit->currentLine()); + metadataList->v.push_back(metadata); + + $$ = metadataList; } | string_literal { auto str = dynamic_pointer_cast($1); - auto stringList = make_shared(); - stringList->v.push_back(str->v); - $$ = stringList; + auto metadataList = make_shared(); + + auto metadata = make_shared(str->v, currentUnit->currentFile(), currentUnit->currentLine()); + metadataList->v.push_back(metadata); + + $$ = metadataList; } ; @@ -2089,21 +2095,21 @@ const_def // ---------------------------------------------------------------------- : ICE_CONST metadata type ICE_IDENTIFIER '=' const_initializer { - auto metadata = dynamic_pointer_cast($2); + auto metadata = dynamic_pointer_cast($2); auto const_type = dynamic_pointer_cast($3); auto ident = dynamic_pointer_cast($4); auto value = dynamic_pointer_cast($6); - $$ = currentUnit->currentContainer()->createConst(ident->v, const_type, metadata->v, value->v, + $$ = currentUnit->currentContainer()->createConst(ident->v, const_type, std::move(metadata->v), value->v, value->valueAsString); } | ICE_CONST metadata type '=' const_initializer { - auto metadata = dynamic_pointer_cast($2); + auto metadata = dynamic_pointer_cast($2); auto const_type = dynamic_pointer_cast($3); auto value = dynamic_pointer_cast($5); currentUnit->error("missing constant name"); - $$ = currentUnit->currentContainer()->createConst(Ice::generateUUID(), const_type, metadata->v, value->v, - value->valueAsString, Dummy); // Dummy + $$ = currentUnit->currentContainer()->createConst(Ice::generateUUID(), const_type, std::move(metadata->v), + value->v, value->valueAsString, Dummy); // Dummy } ; diff --git a/cpp/src/Slice/GrammarUtil.h b/cpp/src/Slice/GrammarUtil.h index ec07a353036..d12f5e53b24 100644 --- a/cpp/src/Slice/GrammarUtil.h +++ b/cpp/src/Slice/GrammarUtil.h @@ -25,10 +25,10 @@ namespace Slice std::string literal; }; - struct StringListTok final : public GrammarBase + struct MetadataListTok final : public GrammarBase { - StringListTok() {} - StringList v; + MetadataListTok() {} + MetadataList v; }; struct TypeStringTok final : public GrammarBase diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 75ae3b0915f..a3ed6471ebb 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -91,11 +91,85 @@ namespace Slice Unit* currentUnit; } +// ---------------------------------------------------------------------- +// Metadata +// ---------------------------------------------------------------------- +Slice::Metadata::Metadata(string rawMetadata, string file, int line) : GrammarBase() +{ + _file = std::move(file); + _line = line; + + // If the metadata contains no colons, then it must be a directive with no arguments. + size_t firstColonPos = rawMetadata.find(':'); + if (firstColonPos == string::npos) + { + _directive = rawMetadata; + _arguments = ""; + return; + } + + // Otherwise, we check whether the colon is for a language prefix or for arguments and split the string accordingly. + size_t secondColonPos = rawMetadata.find(':', firstColonPos + 1); + size_t splitPos; + if (secondColonPos == string::npos) + { + // If the metadata contains only 1 colon, we need to check if it's for a language prefix, or for arguments. + // NOTE: It is important that this list is kept in alphabetical order! + static const string languages[] = {"cpp", "cs", "java", "js", "matlab", "php", "python", "ruby", "swift"}; + string prefix = rawMetadata.substr(0, firstColonPos); + bool isLanguage = binary_search(&languages[0], &languages[sizeof(languages) / sizeof(*languages)], prefix); + if (isLanguage) + { + // If the piece before the colon was a language prefix, don't split up the string. + _directive = rawMetadata; + _arguments = ""; + return; + } + else + { + // If it wasn't a language prefix, then the part after the colon must be arguments. Split it accordingly. + splitPos = firstColonPos; + } + } + else + { + // If the metadata contains 2 colons, than the 1st is for the language prefix, and the 2nd is for the arguments. + splitPos = secondColonPos; + } + + _directive = rawMetadata.substr(0, splitPos); + _arguments = rawMetadata.substr(splitPos + 1); +} + +string_view +Slice::Metadata::directive() const +{ + return _directive; +} + +string_view +Slice::Metadata::arguments() const +{ + return _arguments; +} + +string +Slice::Metadata::file() const +{ + return _file; +} + +int +Slice::Metadata::line() const +{ + return _line; +} + // ---------------------------------------------------------------------- // DefinitionContext // ---------------------------------------------------------------------- -Slice::DefinitionContext::DefinitionContext(int includeLevel, const StringList& metadata) +Slice::DefinitionContext::DefinitionContext(int includeLevel, MetadataList metadata) : _includeLevel(includeLevel), _metadata(metadata), _seenDefinition(false) @@ -133,36 +207,43 @@ Slice::DefinitionContext::setSeenDefinition() _seenDefinition = true; } -bool -Slice::DefinitionContext::hasMetadata(const string& directive) const +MetadataList +Slice::DefinitionContext::getMetadata() const { - return findMetadata(directive).has_value(); + return _metadata; } void -Slice::DefinitionContext::setMetadata(const StringList& metadata) +Slice::DefinitionContext::setMetadata(MetadataList metadata) { _metadata = metadata; initSuppressedWarnings(); } -optional -Slice::DefinitionContext::findMetadata(const string& prefix) const +bool +Slice::DefinitionContext::hasMetadata(string_view directive) const { for (const auto& p : _metadata) { - if (p.find(prefix) == 0) + if (p->directive() == directive) { - return p; + return true; } } - return nullopt; + return false; } -StringList -Slice::DefinitionContext::getMetadata() const +optional +Slice::DefinitionContext::getMetadataArgs(string_view directive) const { - return _metadata; + for (const auto& p : _metadata) + { + if (p->directive() == directive) + { + return string{p->arguments()}; + } + } + return nullopt; } void @@ -185,43 +266,36 @@ void Slice::DefinitionContext::initSuppressedWarnings() { _suppressedWarnings.clear(); - const string prefix = "suppress-warning"; - if (auto meta = findMetadata(prefix)) + if (auto metadata = getMetadataArgs("suppress-warning")) { - string value = *meta; - if (value == prefix) + if (metadata->empty()) { _suppressedWarnings.insert(All); } else { - assert(value.length() > prefix.length()); - if (value[prefix.length()] == ':') + vector result; + IceInternal::splitString(*metadata, ",", result); + for (const auto& p : result) { - value = value.substr(prefix.length() + 1); - vector result; - IceInternal::splitString(value, ",", result); - for (const auto& p : result) + string s = IceInternal::trim(p); + if (s == "all") { - string s = IceInternal::trim(p); - if (s == "all") - { - _suppressedWarnings.insert(All); - } - else if (s == "deprecated") - { - _suppressedWarnings.insert(Deprecated); - } - else if (s == "invalid-metadata") - { - _suppressedWarnings.insert(InvalidMetadata); - } - else - { - ostringstream os; - os << "invalid category `" << s << "' in file metadata suppress-warning"; - warning(InvalidMetadata, "", -1, os.str()); - } + _suppressedWarnings.insert(All); + } + else if (s == "deprecated") + { + _suppressedWarnings.insert(Deprecated); + } + else if (s == "invalid-metadata") + { + _suppressedWarnings.insert(InvalidMetadata); + } + else + { + ostringstream os; + os << "invalid category '" << s << "' in file metadata suppress-warning"; + warning(InvalidMetadata, "", -1, os.str()); } } } @@ -868,71 +942,65 @@ Slice::Contained::includeLevel() const return _includeLevel; } -bool -Slice::Contained::hasMetadata(const string& directive) const -{ - return findMetadata(directive).has_value(); -} - -optional -Slice::Contained::findMetadata(const string& prefix) const -{ - for (const auto& p : _metadata) - { - if (p.find(prefix) == 0) - { - return p; - } - } - return nullopt; -} - -StringList +MetadataList Slice::Contained::getMetadata() const { return _metadata; } void -Slice::Contained::setMetadata(const StringList& metadata) +Slice::Contained::setMetadata(MetadataList metadata) { _metadata = metadata; } -std::optional -Slice::Contained::parseFormatMetadata(const StringList& metadata) +bool +Slice::Contained::hasMetadata(string_view directive) const { - std::optional result; + for (const auto& p : _metadata) + { + if (p->directive() == directive) + { + return true; + } + } + return false; +} - string tag; - string prefix = "format:"; - for (const auto& p : metadata) +optional +Slice::Contained::getMetadataArgs(string_view directive) const +{ + for (const auto& p : _metadata) { - if (p.find(prefix) == 0) + if (p->directive() == directive) { - tag = p; - break; + return string{p->arguments()}; } } + return nullopt; +} - if (!tag.empty()) +std::optional +Slice::Contained::parseFormatMetadata() const +{ + if (auto metadata = getMetadataArgs("format")) { - tag = tag.substr(prefix.size()); - if (tag == "compact") + string arg = *metadata; + if (arg == "compact") { - result = CompactFormat; + return CompactFormat; } - else if (tag == "sliced") + else if (arg == "sliced") { - result = SlicedFormat; + return SlicedFormat; } - else if (tag != "default") // TODO: Allow "default" to be specified as a format value? + else if (arg != "default") // TODO: Allow "default" to be specified as a format value? { // TODO: How to handle invalid format? + return nullopt; } } - - return result; + return nullopt; } bool @@ -944,16 +1012,13 @@ Slice::Contained::isDeprecated() const optional Slice::Contained::getDeprecationReason() const { - const string prefix1 = "deprecate:"; - const string prefix2 = "deprecated:"; - - if (auto meta = findMetadata(prefix1)) + if (auto reason = getMetadataArgs("deprecate")) { - return meta->substr(prefix1.size()); + return *reason; } - if (auto meta = findMetadata(prefix2)) + if (auto reason = getMetadataArgs("deprecated")) { - return meta->substr(prefix2.size()); + return *reason; } return nullopt; @@ -1420,7 +1485,7 @@ Slice::Container::createStruct(const string& name, NodeType nodeType) } SequencePtr -Slice::Container::createSequence(const string& name, const TypePtr& type, const StringList& metadata, NodeType nodeType) +Slice::Container::createSequence(const string& name, const TypePtr& type, MetadataList metadata, NodeType nodeType) { ContainedList matches = _unit->findContents(thisScope() + name); if (!matches.empty()) @@ -1448,7 +1513,7 @@ Slice::Container::createSequence(const string& name, const TypePtr& type, const checkForGlobalDefinition("sequences"); // Don't return here -- we create the sequence anyway. } - SequencePtr p = make_shared(shared_from_this(), name, type, metadata); + SequencePtr p = make_shared(shared_from_this(), name, type, std::move(metadata)); _unit->addContent(p); _contents.push_back(p); return p; @@ -1458,9 +1523,9 @@ DictionaryPtr Slice::Container::createDictionary( const string& name, const TypePtr& keyType, - const StringList& keyMetadata, + MetadataList keyMetadata, const TypePtr& valueType, - const StringList& valueMetadata, + MetadataList valueMetadata, NodeType nodeType) { ContainedList matches = _unit->findContents(thisScope() + name); @@ -1497,7 +1562,13 @@ Slice::Container::createDictionary( } } - DictionaryPtr p = make_shared(shared_from_this(), name, keyType, keyMetadata, valueType, valueMetadata); + DictionaryPtr p = make_shared( + shared_from_this(), + name, + keyType, + std::move(keyMetadata), + valueType, + std::move(valueMetadata)); _unit->addContent(p); _contents.push_back(p); return p; @@ -1542,7 +1613,7 @@ ConstPtr Slice::Container::createConst( const string name, const TypePtr& type, - const StringList& metadata, + MetadataList metadata, const SyntaxTreeBasePtr& valueType, const string& valueString, NodeType nodeType) @@ -1581,7 +1652,8 @@ Slice::Container::createConst( return nullptr; } - ConstPtr p = make_shared(shared_from_this(), name, type, metadata, resolvedValueType, valueString); + ConstPtr p = + make_shared(shared_from_this(), name, type, std::move(metadata), resolvedValueType, valueString); _unit->addContent(p); _contents.push_back(p); return p; @@ -2635,9 +2707,9 @@ Slice::ClassDef::canBeCyclic() const } bool -Slice::ClassDef::inheritsMetadata(const string& metadata) const +Slice::ClassDef::inheritsMetadata(string_view directive) const { - return _base && (_base->hasMetadata(metadata) || _base->inheritsMetadata(metadata)); + return _base && (_base->hasMetadata(directive) || _base->inheritsMetadata(directive)); } bool @@ -3069,11 +3141,11 @@ Slice::InterfaceDef::hasOperations() const } bool -Slice::InterfaceDef::inheritsMetadata(const string& metadata) const +Slice::InterfaceDef::inheritsMetadata(string_view directive) const { for (const auto& p : _bases) { - if (p->hasMetadata(metadata) || p->inheritsMetadata(metadata)) + if (p->hasMetadata(directive) || p->inheritsMetadata(directive)) { return true; } @@ -3459,12 +3531,12 @@ Slice::Operation::sendsOptionals() const std::optional Slice::Operation::format() const { - std::optional format = parseFormatMetadata(getMetadata()); + std::optional format = parseFormatMetadata(); if (!format) { ContainedPtr cont = dynamic_pointer_cast(container()); assert(cont); - format = parseFormatMetadata(cont->getMetadata()); + format = cont->parseFormatMetadata(); } return format; } @@ -3732,9 +3804,9 @@ Slice::Exception::usesClasses() const } bool -Slice::Exception::inheritsMetadata(const string& metadata) const +Slice::Exception::inheritsMetadata(string_view directive) const { - if (_base && (_base->hasMetadata(metadata) || _base->inheritsMetadata(metadata))) + if (_base && (_base->hasMetadata(directive) || _base->inheritsMetadata(directive))) { return true; } @@ -3950,7 +4022,7 @@ Slice::Sequence::type() const return _type; } -StringList +MetadataList Slice::Sequence::typeMetadata() const { return _typeMetadata; @@ -3996,13 +4068,13 @@ Slice::Sequence::Sequence( const ContainerPtr& container, const string& name, const TypePtr& type, - const StringList& typeMetadata) + MetadataList typeMetadata) : SyntaxTreeBase(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name), _type(type), - _typeMetadata(typeMetadata) + _typeMetadata(std::move(typeMetadata)) { } @@ -4022,13 +4094,13 @@ Slice::Dictionary::valueType() const return _valueType; } -StringList +MetadataList Slice::Dictionary::keyMetadata() const { return _keyMetadata; } -StringList +MetadataList Slice::Dictionary::valueMetadata() const { return _valueMetadata; @@ -4126,17 +4198,17 @@ Slice::Dictionary::Dictionary( const ContainerPtr& container, const string& name, const TypePtr& keyType, - const StringList& keyMetadata, + MetadataList keyMetadata, const TypePtr& valueType, - const StringList& valueMetadata) + MetadataList valueMetadata) : SyntaxTreeBase(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name), _keyType(keyType), _valueType(valueType), - _keyMetadata(keyMetadata), - _valueMetadata(valueMetadata) + _keyMetadata(std::move(keyMetadata)), + _valueMetadata(std::move(valueMetadata)) { } @@ -4335,7 +4407,7 @@ Slice::Const::type() const return _type; } -StringList +MetadataList Slice::Const::typeMetadata() const { return _typeMetadata; @@ -4369,13 +4441,13 @@ Slice::Const::Const( const ContainerPtr& container, const string& name, const TypePtr& type, - const StringList& typeMetadata, + MetadataList typeMetadata, const SyntaxTreeBasePtr& valueType, const string& valueString) : SyntaxTreeBase(container->unit()), Contained(container, name), _type(type), - _typeMetadata(typeMetadata), + _typeMetadata(std::move(typeMetadata)), _valueType(valueType), _value(valueString) { @@ -4508,7 +4580,13 @@ Slice::DataMember::DataMember( UnitPtr Slice::Unit::createUnit(bool all, const StringList& defaultFileMetadata) { - UnitPtr unit{new Unit{all, defaultFileMetadata}}; + MetadataList defaultMetadata; + for (const auto& metadataString : defaultFileMetadata) + { + defaultMetadata.push_back(make_shared(metadataString, "", 0)); + } + + UnitPtr unit{new Unit{all, std::move(defaultMetadata)}}; unit->_unit = unit; return unit; } @@ -4687,7 +4765,7 @@ Slice::Unit::currentIncludeLevel() const } void -Slice::Unit::addFileMetadata(const StringList& metadata) +Slice::Unit::addFileMetadata(MetadataList metadata) { DefinitionContextPtr dc = currentDefinitionContext(); assert(dc); @@ -4698,8 +4776,8 @@ Slice::Unit::addFileMetadata(const StringList& metadata) else { // Append the file metadata to any existing metadata (e.g., default file metadata). - StringList l = dc->getMetadata(); - copy(metadata.begin(), metadata.end(), back_inserter(l)); + MetadataList l = dc->getMetadata(); + move(metadata.begin(), metadata.end(), back_inserter(l)); dc->setMetadata(l); } } @@ -4960,11 +5038,11 @@ Slice::Unit::getTopLevelModules(const string& file) const } } -Slice::Unit::Unit(bool all, const StringList& defaultFileMetadata) +Slice::Unit::Unit(bool all, MetadataList defaultFileMetadata) : SyntaxTreeBase(nullptr), Container(nullptr), _all(all), - _defaultFileMetadata(defaultFileMetadata), + _defaultFileMetadata(std::move(defaultFileMetadata)), _errors(0), _currentIncludeLevel(0) diff --git a/cpp/src/Slice/Parser.h b/cpp/src/Slice/Parser.h index a61afc78b3c..aea82853498 100644 --- a/cpp/src/Slice/Parser.h +++ b/cpp/src/Slice/Parser.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ namespace Slice class GrammarBase; class SyntaxTreeBase; + class Metadata; class Type; class Builtin; class Contained; @@ -66,6 +68,7 @@ namespace Slice using GrammarBasePtr = std::shared_ptr; using SyntaxTreeBasePtr = std::shared_ptr; + using MetadataPtr = std::shared_ptr; using TypePtr = std::shared_ptr; using BuiltinPtr = std::shared_ptr; using ContainedPtr = std::shared_ptr; @@ -91,8 +94,9 @@ namespace Slice bool containedCompare(const ContainedPtr& lhs, const ContainedPtr& rhs); bool containedEqual(const ContainedPtr& lhs, const ContainedPtr& rhs); - using TypeList = std::list; using StringList = std::list; + using MetadataList = std::list; + using TypeList = std::list; using ContainedList = std::list; using ModuleList = std::list; using ClassList = std::list; @@ -158,6 +162,50 @@ namespace Slice virtual bool shouldVisitIncludedDefinitions() const { return false; } }; + // ---------------------------------------------------------------------- + // GrammarBase + // ---------------------------------------------------------------------- + + class GrammarBase + { + public: + virtual ~GrammarBase() = default; + }; + + // ---------------------------------------------------------------------- + // Metadata + // ---------------------------------------------------------------------- + + class Metadata final : public GrammarBase + { + public: + Metadata(std::string rawMetadata, std::string file, int line); + std::string_view directive() const; + std::string_view arguments() const; + + std::string file() const; + int line() const; + + friend std::ostream& operator<<(std::ostream& out, const Metadata& metadata); + + private: + std::string _directive; + std::string _arguments; + + std::string _file; + int _line; + }; + + inline std::ostream& operator<<(std::ostream& ostr, const Metadata& metadata) + { + ostr << metadata._directive; + if (!metadata._arguments.empty()) + { + ostr << ":" << metadata._arguments; + } + return ostr; + } + // ---------------------------------------------------------------------- // DefinitionContext // ---------------------------------------------------------------------- @@ -165,7 +213,7 @@ namespace Slice class DefinitionContext final { public: - DefinitionContext(int includeLevel, const StringList& metadata); + DefinitionContext(int includeLevel, MetadataList metadata); std::string filename() const; int includeLevel() const; @@ -174,10 +222,10 @@ namespace Slice void setFilename(const std::string& filename); void setSeenDefinition(); - bool hasMetadata(const std::string& directive) const; - void setMetadata(const StringList& metadata); - std::optional findMetadata(const std::string& prefix) const; - StringList getMetadata() const; + MetadataList getMetadata() const; + void setMetadata(MetadataList metadata); + bool hasMetadata(std::string_view directive) const; + std::optional getMetadataArgs(std::string_view directive) const; /// Emits a warning unless it should be filtered out by a [["suppress-warning"]]. void warning(WarningCategory category, const std::string& file, int line, const std::string& message) const; @@ -187,7 +235,7 @@ namespace Slice void initSuppressedWarnings(); int _includeLevel; - StringList _metadata; + MetadataList _metadata; std::string _filename; bool _seenDefinition; std::set _suppressedWarnings; @@ -233,16 +281,6 @@ namespace Slice }; using CommentPtr = std::shared_ptr; - // ---------------------------------------------------------------------- - // GrammarBase - // ---------------------------------------------------------------------- - - class GrammarBase - { - public: - virtual ~GrammarBase() = default; - }; - // ---------------------------------------------------------------------- // SyntaxTreeBase // ---------------------------------------------------------------------- @@ -342,12 +380,12 @@ namespace Slice int includeLevel() const; - bool hasMetadata(const std::string& directive) const; - std::optional findMetadata(const std::string& prefix) const; - StringList getMetadata() const; - void setMetadata(const StringList& metadata); + MetadataList getMetadata() const; + void setMetadata(MetadataList metadata); + bool hasMetadata(std::string_view directive) const; + std::optional getMetadataArgs(std::string_view directive) const; - static std::optional parseFormatMetadata(const StringList& metadata); + std::optional parseFormatMetadata() const; /// Returns true if this item is deprecated, due to the presence of 'deprecated' metadata. /// @return True if this item has 'deprecated' metadata on it, false otherwise. @@ -370,7 +408,7 @@ namespace Slice int _line; std::string _comment; int _includeLevel; - std::list _metadata; + MetadataList _metadata; }; // ---------------------------------------------------------------------- @@ -389,23 +427,20 @@ namespace Slice InterfaceDeclPtr createInterfaceDecl(const std::string& name); ExceptionPtr createException(const std::string& name, const ExceptionPtr& base, NodeType nodeType = Real); StructPtr createStruct(const std::string& name, NodeType nodeType = Real); - SequencePtr createSequence( - const std::string& name, - const TypePtr& type, - const StringList& metadata, - NodeType nodeType = Real); + SequencePtr + createSequence(const std::string& name, const TypePtr& type, MetadataList metadata, NodeType nodeType = Real); DictionaryPtr createDictionary( const std::string& name, const TypePtr& keyType, - const StringList& keyMetadata, + MetadataList keyMetadata, const TypePtr& valueType, - const StringList& valueMetadata, + MetadataList valueMetadata, NodeType nodeType = Real); EnumPtr createEnum(const std::string& name, NodeType nodeType = Real); ConstPtr createConst( const std::string name, const TypePtr& constType, - const StringList& metadata, + MetadataList metadata, const SyntaxTreeBasePtr& valueType, const std::string& value, NodeType nodeType = Real); @@ -541,7 +576,7 @@ namespace Slice DataMemberList classDataMembers() const; DataMemberList allClassDataMembers() const; bool canBeCyclic() const; - bool inheritsMetadata(const std::string& metadata) const; + bool inheritsMetadata(std::string_view directive) const; bool hasBaseDataMembers() const; void visit(ParserVisitor* visitor) final; int compactId() const; @@ -675,7 +710,7 @@ namespace Slice OperationList operations() const; OperationList allOperations() const; bool hasOperations() const; - bool inheritsMetadata(const std::string& metadata) const; + bool inheritsMetadata(std::string_view directive) const; std::string kindOf() const final; void visit(ParserVisitor* visitor) final; @@ -716,7 +751,7 @@ namespace Slice ExceptionList allBases() const; bool isBaseOf(const ExceptionPtr& otherException) const; bool usesClasses() const; - bool inheritsMetadata(const std::string& metadata) const; + bool inheritsMetadata(std::string_view metadata) const; bool hasBaseDataMembers() const; std::string kindOf() const final; void visit(ParserVisitor* visitor) final; @@ -761,9 +796,9 @@ namespace Slice const ContainerPtr& container, const std::string& name, const TypePtr& type, - const StringList& typeMetadata); + MetadataList typeMetadata); TypePtr type() const; - StringList typeMetadata() const; + MetadataList typeMetadata() const; bool usesClasses() const final; size_t minWireSize() const final; std::string getOptionalFormat() const final; @@ -773,7 +808,7 @@ namespace Slice private: TypePtr _type; - StringList _typeMetadata; + MetadataList _typeMetadata; }; // ---------------------------------------------------------------------- @@ -787,13 +822,13 @@ namespace Slice const ContainerPtr& container, const std::string& name, const TypePtr& keyType, - const StringList& keyMetadata, + MetadataList keyMetadata, const TypePtr& valueType, - const StringList& valueMetadata); + MetadataList valueMetadata); TypePtr keyType() const; TypePtr valueType() const; - StringList keyMetadata() const; - StringList valueMetadata() const; + MetadataList keyMetadata() const; + MetadataList valueMetadata() const; bool usesClasses() const final; size_t minWireSize() const final; std::string getOptionalFormat() const final; @@ -806,8 +841,8 @@ namespace Slice private: TypePtr _keyType; TypePtr _valueType; - StringList _keyMetadata; - StringList _valueMetadata; + MetadataList _keyMetadata; + MetadataList _valueMetadata; }; // ---------------------------------------------------------------------- @@ -866,11 +901,11 @@ namespace Slice const ContainerPtr& container, const std::string& name, const TypePtr& type, - const StringList& typeMetadata, + MetadataList typeMetadata, const SyntaxTreeBasePtr& valueType, const std::string& valueString); TypePtr type() const; - StringList typeMetadata() const; + MetadataList typeMetadata() const; SyntaxTreeBasePtr valueType() const; std::string value() const; std::string kindOf() const final; @@ -878,7 +913,7 @@ namespace Slice private: TypePtr _type; - StringList _typeMetadata; + MetadataList _typeMetadata; SyntaxTreeBasePtr _valueType; std::string _value; }; @@ -961,7 +996,7 @@ namespace Slice int setCurrentFile(const std::string& currentFile, int lineNumber); int currentIncludeLevel() const; - void addFileMetadata(const StringList& metadata); + void addFileMetadata(MetadataList metadata); void setSeenDefinition(); @@ -1000,13 +1035,13 @@ namespace Slice std::set getTopLevelModules(const std::string& file) const; private: - Unit(bool all, const StringList& defaultFileMetadata); + Unit(bool all, MetadataList defaultFileMetadata); void pushDefinitionContext(); void popDefinitionContext(); bool _all; - StringList _defaultFileMetadata; + MetadataList _defaultFileMetadata; int _errors; std::string _currentComment; int _currentIncludeLevel; diff --git a/cpp/src/Slice/Scanner.cpp b/cpp/src/Slice/Scanner.cpp index 958383a248d..a9551ccbe6d 100644 --- a/cpp/src/Slice/Scanner.cpp +++ b/cpp/src/Slice/Scanner.cpp @@ -343,7 +343,7 @@ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. + * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 @@ -356,12 +356,11 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; -typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; +typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; @@ -481,7 +480,7 @@ typedef size_t yy_size_t; #endif /* %if-not-reentrant */ -extern yy_size_t yyleng; +extern int yyleng; /* %endif */ /* %if-c-only */ @@ -493,10 +492,10 @@ extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - + #define YY_LESS_LINENO(n) #define YY_LINENO_REWIND_TO(ptr) - + /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ @@ -534,7 +533,7 @@ struct yy_buffer_state /* Number of characters read into yy_ch_buf, not including EOB * characters. */ - yy_size_t yy_n_chars; + int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to @@ -615,8 +614,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ /* %not-for-header */ /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; -static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ -yy_size_t yyleng; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = NULL; @@ -646,7 +645,7 @@ static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); -YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); /* %endif */ @@ -715,7 +714,7 @@ static void yynoreturn yy_fatal_error ( const char* msg ); (yytext_ptr) = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ (yytext_ptr) -= (yy_more_len); \ - yyleng = (yy_size_t) (yy_cp - (yytext_ptr)); \ + yyleng = (int) (yy_cp - (yytext_ptr)); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ @@ -1171,7 +1170,7 @@ namespace #define YY_USER_ACTION preAction(); #define YY_FATAL_ERROR(msg) fatalError(msg); -#line 1174 "src/Slice/Scanner.cpp" +#line 1173 "src/Slice/Scanner.cpp" #line 59 "src/Slice/Scanner.l" /* Changes the default prefix of 'yy' to 'slice_' for functions and variables in the generated code. */ /* Instructs flex to not suppress any warnings when generating the scanner. */ @@ -1197,7 +1196,7 @@ namespace /* The scanner also has a built in 'INITIAL' start-condition state, which is the state the scanner is initialized in. * We use it solely to check for and consume any BOMs at the start of files. See Bug 3140. */ -#line 1200 "src/Slice/Scanner.cpp" +#line 1199 "src/Slice/Scanner.cpp" #define INITIAL 0 #define C_COMMENT 1 @@ -1258,7 +1257,7 @@ extern int yywrap ( void ); /* %not-for-header */ #ifndef YY_NO_UNPUT - + #endif /* %ok-for-header */ @@ -1290,13 +1289,13 @@ static int input ( void ); static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = NULL; - + static void yy_push_state ( int _new_state ); - + static void yy_pop_state ( void ); - + static int yy_top_state ( void ); - + /* %endif */ /* Amount of stuff to slurp up with each read. */ @@ -1330,7 +1329,7 @@ static int input ( void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - yy_size_t n; \ + int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -1437,11 +1436,11 @@ YY_DECL yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; - + YYSTYPE * yylval; - + YYLTYPE * yylloc; - + yylval = yylval_param; yylloc = yylloc_param; @@ -1487,7 +1486,7 @@ YY_DECL /* ========== Literals ========== */ /* Matches the start of a double-quoted string literal. */ -#line 1490 "src/Slice/Scanner.cpp" +#line 1489 "src/Slice/Scanner.cpp" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1810,11 +1809,11 @@ YY_RULE_SETUP ftp->v = strtod(literal.c_str(), 0); if ((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE) { - currentUnit->error("floating-point constant `" + string(yytext) + "' too large (overflow)"); + currentUnit->error("floating-point constant `" + string{yytext} + "' too large (overflow)"); } else if (ftp->v == 0 && errno == ERANGE) { - currentUnit->error("floating-point constant `" + string(yytext) + "' too small (underflow)"); + currentUnit->error("floating-point constant `" + string{yytext} + "' too small (underflow)"); } return ICE_FLOATING_POINT_LITERAL; } @@ -2118,7 +2117,7 @@ YY_RULE_SETUP #line 528 "src/Slice/Scanner.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 2121 "src/Slice/Scanner.cpp" +#line 2120 "src/Slice/Scanner.cpp" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(SLICE): case YY_STATE_EOF(METADATA): @@ -2324,7 +2323,7 @@ static int yy_get_next_buffer (void) else { - yy_size_t num_to_read = + int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) @@ -2338,7 +2337,7 @@ static int yy_get_next_buffer (void) if ( b->yy_is_our_buffer ) { - yy_size_t new_size = b->yy_buf_size * 2; + int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; @@ -2396,7 +2395,7 @@ static int yy_get_next_buffer (void) if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) @@ -2425,7 +2424,7 @@ static int yy_get_next_buffer (void) { yy_state_type yy_current_state; char *yy_cp; - + /* %% [15.0] code to get the start state into yy_current_state goes here */ yy_current_state = (yy_start); yy_current_state += YY_AT_BOL(); @@ -2503,7 +2502,7 @@ static int yy_get_next_buffer (void) /* %endif */ { int c; - + *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) @@ -2518,7 +2517,7 @@ static int yy_get_next_buffer (void) else { /* need more input */ - yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) @@ -2575,7 +2574,7 @@ static int yy_get_next_buffer (void) /** Immediately switch to a different input stream. * @param input_file A readable stream. - * + * * @note This function does not reset the start condition to @c INITIAL . */ /* %if-c-only */ @@ -2584,7 +2583,7 @@ static int yy_get_next_buffer (void) /* %if-c++-only */ /* %endif */ { - + if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = @@ -2600,7 +2599,7 @@ static int yy_get_next_buffer (void) /** Switch to a different input buffer. * @param new_buffer The new input buffer. - * + * */ /* %if-c-only */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) @@ -2608,7 +2607,7 @@ static int yy_get_next_buffer (void) /* %if-c++-only */ /* %endif */ { - + /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); @@ -2656,7 +2655,7 @@ static void yy_load_buffer_state (void) /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * + * * @return the allocated buffer state. */ /* %if-c-only */ @@ -2666,7 +2665,7 @@ static void yy_load_buffer_state (void) /* %endif */ { YY_BUFFER_STATE b; - + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); @@ -2692,7 +2691,7 @@ static void yy_load_buffer_state (void) /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() - * + * */ /* %if-c-only */ void yy_delete_buffer (YY_BUFFER_STATE b ) @@ -2700,7 +2699,7 @@ static void yy_load_buffer_state (void) /* %if-c++-only */ /* %endif */ { - + if ( ! b ) return; @@ -2725,7 +2724,7 @@ static void yy_load_buffer_state (void) { int oerrno = errno; - + yy_flush_buffer( b ); /* %if-c-only */ @@ -2747,7 +2746,7 @@ static void yy_load_buffer_state (void) /* %if-c-only */ b->yy_is_interactive = 0; - + /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2756,7 +2755,7 @@ static void yy_load_buffer_state (void) /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * + * */ /* %if-c-only */ void yy_flush_buffer (YY_BUFFER_STATE b ) @@ -2790,7 +2789,7 @@ static void yy_load_buffer_state (void) * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. - * + * */ /* %if-c-only */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) @@ -2826,7 +2825,7 @@ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) /* %if-c-or-c++ */ /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. - * + * */ /* %if-c-only */ void yypop_buffer_state (void) @@ -2860,7 +2859,7 @@ static void yyensure_buffer_stack (void) /* %endif */ { yy_size_t num_to_alloc; - + if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this @@ -2972,7 +2971,7 @@ static void yynoreturn yy_fatal_error (const char* msg ) do \ { \ /* Undo effects of setting up yytext. */ \ - yy_size_t yyless_macro_arg = (n); \ + int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ @@ -2989,7 +2988,7 @@ static void yynoreturn yy_fatal_error (const char* msg ) /* %endif */ /** Get the current token. - * + * */ /* %if-reentrant */ @@ -3040,7 +3039,7 @@ static int yy_init_globals (void) /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { - + /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer( YY_CURRENT_BUFFER ); @@ -3073,7 +3072,7 @@ int yylex_destroy (void) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, const char * s2, int n ) { - + int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; @@ -3098,7 +3097,7 @@ void *yyalloc (yy_size_t size ) void *yyrealloc (void * ptr, yy_size_t size ) { - + /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter diff --git a/cpp/src/Slice/Scanner.l b/cpp/src/Slice/Scanner.l index 0106155247a..16f69c58716 100644 --- a/cpp/src/Slice/Scanner.l +++ b/cpp/src/Slice/Scanner.l @@ -304,11 +304,11 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?{dec}+{expo ftp->v = strtod(literal.c_str(), 0); if ((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE) { - currentUnit->error("floating-point constant `" + string(yytext) + "' too large (overflow)"); + currentUnit->error("floating-point constant `" + string{yytext} + "' too large (overflow)"); } else if (ftp->v == 0 && errno == ERANGE) { - currentUnit->error("floating-point constant `" + string(yytext) + "' too small (underflow)"); + currentUnit->error("floating-point constant `" + string{yytext} + "' too small (underflow)"); } return ICE_FLOATING_POINT_LITERAL; } diff --git a/cpp/src/ice2slice/Gen.cpp b/cpp/src/ice2slice/Gen.cpp index 2665a53e6fe..d0a1f7fb877 100644 --- a/cpp/src/ice2slice/Gen.cpp +++ b/cpp/src/ice2slice/Gen.cpp @@ -100,12 +100,10 @@ namespace assert(m); - static const string prefix = "cs:namespace:"; - - if (auto meta = m->findMetadata(prefix)) + if (auto metadata = m->getMetadataArgs("cs:namespace")) { hasCSharpNamespaceAttribute = true; - return meta->substr(prefix.size()) + "." + csharpNamespace; + return *metadata + "." + csharpNamespace; } else { @@ -566,14 +564,11 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p) out << nl << "typealias " << p->name() << " = "; - StringList metadata = p->getMetadata(); - const string csGenericPrefix = "cs:generic:"; - for (StringList::iterator q = metadata.begin(); q != metadata.end(); ++q) + for (const auto& metadata : p->getMetadata()) { - string& s = *q; - if (s.find(csGenericPrefix) == 0) + if (metadata->directive() == "cs:generic") { - string type = s.substr(csGenericPrefix.size()); + string_view type = metadata->arguments(); if ((type == "LinkedList" || type == "Queue" || type == "Stack") && p->type()->isClassType()) { continue; // Ignored for objects @@ -607,12 +602,9 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) out << nl << "typealias " << p->name() << " = "; - StringList metadata = p->getMetadata(); - const string csGenericPrefix = "cs:generic:SortedDictionary"; - for (StringList::iterator q = metadata.begin(); q != metadata.end(); ++q) + for (const auto& metadata : p->getMetadata()) { - string& s = *q; - if (s.find(csGenericPrefix) == 0) + if (metadata->directive() == "cs:generic" && metadata->arguments() == "SortedDictionary") { out << "[cs::type(\"[System.Collections.Generic.SortedDictionary<" // TODO the generic arguments must be the IceRPC C# mapped types diff --git a/cpp/src/slice2cpp/CPlusPlusUtil.cpp b/cpp/src/slice2cpp/CPlusPlusUtil.cpp index cddf3bea664..b0cf8fc39e7 100644 --- a/cpp/src/slice2cpp/CPlusPlusUtil.cpp +++ b/cpp/src/slice2cpp/CPlusPlusUtil.cpp @@ -19,7 +19,7 @@ using namespace IceInternal; namespace { - string stringTypeToString(const TypePtr&, const StringList& metadata, TypeContext typeCtx) + string stringTypeToString(const TypePtr&, const MetadataList& metadata, TypeContext typeCtx) { string strType = findMetadata(metadata, typeCtx); @@ -41,7 +41,7 @@ namespace } string - sequenceTypeToString(const SequencePtr& seq, const string& scope, const StringList& metadata, TypeContext typeCtx) + sequenceTypeToString(const SequencePtr& seq, const string& scope, const MetadataList& metadata, TypeContext typeCtx) { string seqType = findMetadata(metadata, typeCtx); if (!seqType.empty()) @@ -79,7 +79,7 @@ namespace string dictionaryTypeToString( const DictionaryPtr& dict, const string& scope, - const StringList& metadata, + const MetadataList& metadata, TypeContext typeCtx) { const string dictType = findMetadata(metadata, typeCtx); @@ -119,7 +119,7 @@ namespace } // Do we pass this type by value when it's an input parameter? - bool inputParamByValue(const TypePtr& type, const StringList& metadata) + bool inputParamByValue(const TypePtr& type, const MetadataList& metadata) { BuiltinPtr builtin = dynamic_pointer_cast(type); if ((builtin && (!builtin->isVariableLength() || builtin->kind() == Builtin::KindString))) @@ -132,31 +132,18 @@ namespace } if (dynamic_pointer_cast(type) || dynamic_pointer_cast(type)) { - static const string prefix = "cpp:"; - // Return true for view-type (sequence and dictionary) and array (sequence only) - for (const auto& str : metadata) + for (const auto& meta : metadata) { - if (str.find(prefix) == 0) + string_view directive = meta->directive(); + string_view arguments = meta->arguments(); + if (directive == "cpp:view-type" && !arguments.empty()) { - string::size_type pos = str.find(':', prefix.size()); - if (pos != string::npos) - { - string ss = str.substr(prefix.size()); - if (ss.find("view-type:") == 0) - { - return true; - } - // else check remaining metadata - } - else - { - if (str.substr(prefix.size()) == "array") - { - return true; - } - // else check remaining metadata - } + return true; + } + if (directive == "cpp:array" && arguments.empty()) + { + return true; } } } @@ -169,7 +156,7 @@ namespace bool optional, const string& scope, const string& fixedName, - const StringList& metadata, + const MetadataList& metadata, TypeContext typeCtx) { string s = typeToString(type, optional, scope, metadata, typeCtx); @@ -473,7 +460,7 @@ Slice::typeToString( const TypePtr& type, bool optional, const string& scope, - const StringList& metadata, + const MetadataList& metadata, TypeContext typeCtx) { assert(type); @@ -568,7 +555,7 @@ Slice::inputTypeToString( const TypePtr& type, bool optional, const string& scope, - const StringList& metadata, + const MetadataList& metadata, TypeContext typeCtx) { assert(type); @@ -592,7 +579,7 @@ Slice::outputTypeToString( const TypePtr& type, bool optional, const string& scope, - const StringList& metadata, + const MetadataList& metadata, TypeContext typeCtx) { assert(type); @@ -956,60 +943,40 @@ Slice::writeIceTuple(::IceInternal::Output& out, const DataMemberList& dataMembe } string -Slice::findMetadata(const StringList& metadata, TypeContext typeCtx) +Slice::findMetadata(const MetadataList& metadata, TypeContext typeCtx) { - static const string prefix = "cpp:"; - - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + for (const auto& meta : metadata) { - string str = *q; - if (str.find(prefix) == 0) - { - string::size_type pos = str.find(':', prefix.size()); - - // If a marshal param, we first check view-type then type. Otherwise, we check type. - // Then, if a marshal param or an unmarshal param where the underlying InputStream buffer remains valid for - // a while, we check for "array". + string_view directive = meta->directive(); - if (pos != string::npos) + // If a marshal param, we first check view-type then type. Otherwise, we check type. + // Then, if a marshal param or an unmarshal param where the underlying InputStream buffer remains valid for + // a while, we check for "array". + if ((typeCtx & TypeContext::MarshalParam) != TypeContext::None) + { + if (directive == "cpp:view-type") { - string ss = str.substr(prefix.size()); + return string{meta->arguments()}; + } + } - if ((typeCtx & TypeContext::MarshalParam) != TypeContext::None) - { - if (ss.find("view-type:") == 0) - { - return str.substr(pos + 1); - } - } + if (directive == "cpp:type") + { + return string{meta->arguments()}; + } - if (ss.find("type:") == 0) - { - return str.substr(pos + 1); - } - } - else if ((typeCtx & (TypeContext::MarshalParam | TypeContext::UnmarshalParamZeroCopy)) != TypeContext::None) - { - string ss = str.substr(prefix.size()); - if (ss == "array") - { - return "%array"; - } - } - // - // Otherwise if the data is "unscoped" it is returned. - // - else + if ((typeCtx & (TypeContext::MarshalParam | TypeContext::UnmarshalParamZeroCopy)) != TypeContext::None) + { + if (directive == "cpp:array") { - string ss = str.substr(prefix.size()); - if (ss == "unscoped") - { - return "%unscoped"; - } + return "%array"; } } + else if (directive == "cpp:unscoped") // TODO: The 'else if' here seems dubious. Should probably just be 'if'. + { + return "%unscoped"; + } } - return ""; } @@ -1024,14 +991,16 @@ Slice::inWstringModule(const SequencePtr& seq) { break; } - StringList metadata = mod->getMetadata(); - if (find(metadata.begin(), metadata.end(), "cpp:type:wstring") != metadata.end()) - { - return true; - } - else if (find(metadata.begin(), metadata.end(), "cpp:type:string") != metadata.end()) + if (auto argument = mod->getMetadataArgs("cpp:type")) { - return false; + if (argument == "wstring") + { + return true; + } + else if (argument == "string") + { + return false; + } } cont = mod->container(); } diff --git a/cpp/src/slice2cpp/CPlusPlusUtil.h b/cpp/src/slice2cpp/CPlusPlusUtil.h index 313562be14b..05867fd7952 100644 --- a/cpp/src/slice2cpp/CPlusPlusUtil.h +++ b/cpp/src/slice2cpp/CPlusPlusUtil.h @@ -31,7 +31,7 @@ namespace Slice const TypePtr&, bool, const std::string& = "", - const StringList& = StringList(), + const MetadataList& = MetadataList(), TypeContext = TypeContext::None); // TODO: find a better name. @@ -40,7 +40,7 @@ namespace Slice const TypePtr&, bool, const std::string& = "", - const StringList& = StringList(), + const MetadataList& = MetadataList(), TypeContext = TypeContext::None); // TODO: find a better name. @@ -49,7 +49,7 @@ namespace Slice const TypePtr&, bool, const std::string& = "", - const StringList& = StringList(), + const MetadataList& = MetadataList(), TypeContext = TypeContext::None); std::string operationModeToString(Operation::Mode); @@ -78,7 +78,7 @@ namespace Slice void writeIceTuple(::IceInternal::Output&, const DataMemberList&, TypeContext); - std::string findMetadata(const StringList&, TypeContext = TypeContext::None); + std::string findMetadata(const MetadataList&, TypeContext = TypeContext::None); bool inWstringModule(const SequencePtr&); } diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 789ce39c7a5..2827198fa92 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -94,7 +94,7 @@ namespace const SyntaxTreeBasePtr& valueType, const string& value, TypeContext typeContext, - const StringList& metadata, + const MetadataList& metadata, const string& scope) { ConstPtr constant = dynamic_pointer_cast(valueType); @@ -414,12 +414,13 @@ namespace UnitPtr unt = p->container()->unit(); string file = p->file(); assert(!file.empty()); - static const string prefix = "cpp:doxygen:include:"; DefinitionContextPtr dc = unt->findDefinitionContext(file); assert(dc); - if (auto meta = dc->findMetadata(prefix)) + + // TODO: why do we ignore all instances of this metadata except the first? + if (auto headerFile = dc->getMetadataArgs("cpp:doxygen:include")) { - out << nl << " * \\headerfile " << meta->substr(prefix.size()); + out << nl << " * \\headerfile " << *headerFile; } } @@ -675,10 +676,9 @@ Slice::Gen::generate(const UnitPtr& p) // if (_dllExport.empty()) { - static const string dllExportPrefix = "cpp:dll-export:"; - if (auto meta = dc->findMetadata(dllExportPrefix)) + if (auto dllExport = dc->getMetadataArgs("cpp:dll-export")) { - _dllExport = meta->substr(dllExportPrefix.size()); + _dllExport = *dllExport; } } @@ -767,44 +767,45 @@ Slice::Gen::generate(const UnitPtr& p) } } - // Emit #include statements for any cpp:include metadata directives in the top-level Slice file. + // Emit #include statements for any 'cpp:include' metadata directives in the top-level Slice file. { - StringList fileMetadata = dc->getMetadata(); - for (StringList::const_iterator q = fileMetadata.begin(); q != fileMetadata.end();) + MetadataList fileMetadata = dc->getMetadata(); + for (MetadataList::const_iterator q = fileMetadata.begin(); q != fileMetadata.end();) { - string metadata = *q++; - static const string includePrefix = "cpp:include:"; - static const string sourceIncludePrefix = "cpp:source-include:"; - if (metadata.find(includePrefix) == 0) + MetadataPtr metadata = *q++; + string_view directive = metadata->directive(); + string_view arguments = metadata->arguments(); + + if (directive == "cpp:include") { - if (metadata.size() > includePrefix.size()) + if (!arguments.empty()) { - H << nl << "#include <" << metadata.substr(includePrefix.size()) << ">"; + H << nl << "#include <" << arguments << ">"; } else { ostringstream ostr; - ostr << "ignoring invalid file metadata `" << metadata << "'"; + ostr << "ignoring invalid file metadata '" << *metadata << "'"; dc->warning(InvalidMetadata, file, -1, ostr.str()); fileMetadata.remove(metadata); } } - else if (metadata.find(sourceIncludePrefix) == 0) + else if (directive == "cpp:source-include") { - if (metadata.size() > sourceIncludePrefix.size()) + if (!arguments.empty()) { - C << nl << "#include <" << metadata.substr(sourceIncludePrefix.size()) << ">"; + C << nl << "#include <" << arguments << ">"; } else { ostringstream ostr; - ostr << "ignoring invalid file metadata `" << metadata << "'"; + ostr << "ignoring invalid file metadata '" << *metadata << "'"; dc->warning(InvalidMetadata, file, -1, ostr.str()); fileMetadata.remove(metadata); } } } - dc->setMetadata(fileMetadata); + dc->setMetadata(std::move(fileMetadata)); } if (!dc->hasMetadata("cpp:no-default-include")) @@ -900,94 +901,96 @@ Slice::Gen::validateMetadata(const UnitPtr& u) bool Slice::Gen::MetadataVisitor::visitUnitStart(const UnitPtr& unit) { - static const string prefix = "cpp:"; - - // // Validate file metadata in the top-level file and all included files. - // for (const string& file : unit->allFiles()) { DefinitionContextPtr dc = unit->findDefinitionContext(file); - StringList fileMetadata = dc->getMetadata(); + MetadataList fileMetadata = dc->getMetadata(); assert(dc); - int headerExtension = 0; - int sourceExtension = 0; - int dllExport = 0; - for (StringList::const_iterator r = fileMetadata.begin(); r != fileMetadata.end();) + bool seenHeaderExtension = false; + bool seenSourceExtension = false; + bool seenDllExport = false; + + for (MetadataList::const_iterator r = fileMetadata.begin(); r != fileMetadata.end();) { - string s = *r++; - if (s.find(prefix) == 0) + MetadataPtr s = *r++; + string_view directive = s->directive(); + string_view arguments = s->arguments(); + + if (directive.find("cpp:") == 0) { - static const string cppIncludePrefix = "cpp:include:"; + static const string cppIncludePrefix = "cpp:include"; static const string cppNoDefaultInclude = "cpp:no-default-include"; static const string cppNoStream = "cpp:no-stream"; static const string cppSourceIncludePrefix = "cpp:source-include"; - static const string cppHeaderExtPrefix = "cpp:header-ext:"; - static const string cppSourceExtPrefix = "cpp:source-ext:"; - static const string cppDllExportPrefix = "cpp:dll-export:"; - static const string cppDoxygenIncludePrefix = "cpp:doxygen:include:"; + static const string cppHeaderExtPrefix = "cpp:header-ext"; + static const string cppSourceExtPrefix = "cpp:source-ext"; + static const string cppDllExportPrefix = "cpp:dll-export"; + static const string cppDoxygenIncludePrefix = "cpp:doxygen"; - if (s == cppNoDefaultInclude || s == cppNoStream) + if (directive == cppNoDefaultInclude || directive == cppNoStream) { continue; } - else if (s.find(cppIncludePrefix) == 0 && s.size() > cppIncludePrefix.size()) + else if (directive == cppIncludePrefix && !arguments.empty()) { continue; } - else if (s.find(cppSourceIncludePrefix) == 0 && s.size() > cppSourceIncludePrefix.size()) + else if (directive == cppSourceIncludePrefix && !arguments.empty()) { continue; } - else if (s.find(cppHeaderExtPrefix) == 0 && s.size() > cppHeaderExtPrefix.size()) + else if (directive == cppHeaderExtPrefix && !arguments.empty()) { - headerExtension++; - if (headerExtension > 1) + if (seenHeaderExtension) { ostringstream ostr; - ostr << "ignoring invalid file metadata `" << s << "': directive can appear only once per file"; + ostr << "ignoring invalid file metadata '" << *s + << "': directive can appear only once per file"; dc->warning(InvalidMetadata, file, -1, ostr.str()); fileMetadata.remove(s); } + seenHeaderExtension = true; continue; } - else if (s.find(cppSourceExtPrefix) == 0 && s.size() > cppSourceExtPrefix.size()) + else if (directive == cppSourceExtPrefix && !arguments.empty()) { - sourceExtension++; - if (sourceExtension > 1) + if (seenSourceExtension) { ostringstream ostr; - ostr << "ignoring invalid file metadata `" << s << "': directive can appear only once per file"; + ostr << "ignoring invalid file metadata '" << *s + << "': directive can appear only once per file"; dc->warning(InvalidMetadata, file, -1, ostr.str()); fileMetadata.remove(s); } + seenSourceExtension = true; continue; } - else if (s.find(cppDllExportPrefix) == 0 && s.size() > cppDllExportPrefix.size()) + else if (directive == cppDllExportPrefix && !arguments.empty()) { - dllExport++; - if (dllExport > 1) + if (seenDllExport) { ostringstream ostr; - ostr << "ignoring invalid file metadata `" << s << "': directive can appear only once per file"; + ostr << "ignoring invalid file metadata '" << *s + << "': directive can appear only once per file"; dc->warning(InvalidMetadata, file, -1, ostr.str()); - fileMetadata.remove(s); } + seenDllExport = true; continue; } - else if (s.find(cppDoxygenIncludePrefix) == 0 && s.size() > cppDoxygenIncludePrefix.size()) + else if (directive == cppDoxygenIncludePrefix && arguments.find("include:") == 0) { continue; } ostringstream ostr; - ostr << "ignoring invalid file metadata `" << s << "'"; + ostr << "ignoring invalid file metadata '" << *s << "'"; dc->warning(InvalidMetadata, file, -1, ostr.str()); fileMetadata.remove(s); } } - dc->setMetadata(fileMetadata); + dc->setMetadata(std::move(fileMetadata)); } return true; @@ -996,39 +999,34 @@ Slice::Gen::MetadataVisitor::visitUnitStart(const UnitPtr& unit) bool Slice::Gen::MetadataVisitor::visitModuleStart(const ModulePtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); return true; } void Slice::Gen::MetadataVisitor::visitClassDecl(const ClassDeclPtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); } bool Slice::Gen::MetadataVisitor::visitClassDefStart(const ClassDefPtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); return true; } bool Slice::Gen::MetadataVisitor::visitExceptionStart(const ExceptionPtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); return true; } bool Slice::Gen::MetadataVisitor::visitStructStart(const StructPtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); return true; } @@ -1040,21 +1038,20 @@ Slice::Gen::MetadataVisitor::visitOperation(const OperationPtr& p) { const DefinitionContextPtr dc = p->unit()->findDefinitionContext(p->file()); assert(dc); - StringList metadata = p->getMetadata(); - for (StringList::const_iterator q = metadata.begin(); q != metadata.end();) + MetadataList metadata = p->getMetadata(); + for (MetadataList::const_iterator q = metadata.begin(); q != metadata.end();) { - string s = *q++; - if (s.find("cpp:type:") == 0 || s.find("cpp:view-type:") == 0 || s == "cpp:array") + MetadataPtr s = *q++; + string_view directive = s->directive(); + if (directive == "cpp:type" || directive == "cpp:view-type" || directive == "cpp:array") { - dc->warning( - InvalidMetadata, - p->file(), - p->line(), - "ignoring invalid metadata `" + s + "' for operation with void return type"); + ostringstream ostr; + ostr << "ignoring invalid metadata '" << *s << "' for operation with void return type"; + dc->warning(InvalidMetadata, p->file(), p->line(), ostr.str()); metadata.remove(s); } } - p->setMetadata(metadata); + p->setMetadata(std::move(metadata)); } else { @@ -1070,75 +1067,73 @@ Slice::Gen::MetadataVisitor::visitOperation(const OperationPtr& p) void Slice::Gen::MetadataVisitor::visitDataMember(const DataMemberPtr& p) { - StringList metadata = validate(p->type(), p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p->type(), p->getMetadata(), p->file(), p->line())); } void Slice::Gen::MetadataVisitor::visitSequence(const SequencePtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); } void Slice::Gen::MetadataVisitor::visitDictionary(const DictionaryPtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); } void Slice::Gen::MetadataVisitor::visitEnum(const EnumPtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); } void Slice::Gen::MetadataVisitor::visitConst(const ConstPtr& p) { - StringList metadata = validate(p, p->getMetadata(), p->file(), p->line()); - p->setMetadata(metadata); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); } -StringList +MetadataList Slice::Gen::MetadataVisitor::validate( const SyntaxTreeBasePtr& cont, - const StringList& metadata, + MetadataList metadata, const string& file, int line, bool operation) { - static const string cppPrefix = "cpp:"; - const UnitPtr ut = cont->unit(); const DefinitionContextPtr dc = ut->findDefinitionContext(file); assert(dc); - StringList newMetadata = metadata; - for (const string& s : metadata) + + for (MetadataList::const_iterator q = metadata.begin(); q != metadata.end();) { + MetadataPtr meta = *q++; + string_view directive = meta->directive(); + string_view arguments = meta->arguments(); + // Issue friendly warning for cpp11 and cpp98 metadata what were removed as Slice does not issue warnings // for unknown "top-level" metadata. - if (s.find("cpp11:") == 0 || s.find("cpp98:") == 0) + if (directive.find("cpp11") == 0 || directive.find("cpp98") == 0) { - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + s + "'"); - newMetadata.remove(s); + ostringstream ostr; + ostr << "ignoring invalid metadata '" << *meta << "'"; + dc->warning(InvalidMetadata, file, line, ostr.str()); + metadata.remove(meta); continue; } - if (s.find(cppPrefix) != 0) + if (directive.find("cpp:") != 0) { continue; } - if (operation && s == "cpp:const") + if (operation && directive == "cpp:const" && arguments.empty()) { continue; } - string ss = s.substr(cppPrefix.size()); - if (ss == "type:wstring" || ss == "type:string") + if (directive == "cpp:type" && (arguments == "wstring" || arguments == "string")) { BuiltinPtr builtin = dynamic_pointer_cast(cont); ModulePtr module = dynamic_pointer_cast(cont); @@ -1154,50 +1149,61 @@ Slice::Gen::MetadataVisitor::validate( } if (dynamic_pointer_cast(cont)) { - if (ss.find("type:") == 0 || ss.find("view-type:") == 0 || ss == "array") + if ((directive == "cpp:type" || directive == "cpp:view-type") && !arguments.empty()) + { + continue; + } + if (directive == "cpp:array" && arguments.empty()) { continue; } } - if (dynamic_pointer_cast(cont) && (ss.find("type:") == 0 || ss.find("view-type:") == 0)) + if (dynamic_pointer_cast(cont)) { - continue; + if ((directive == "cpp:type" || directive == "cpp:view-type") && !arguments.empty()) + { + continue; + } } - if (dynamic_pointer_cast(cont) && ss == "ice_print") + if (dynamic_pointer_cast(cont) && directive == "cpp:ice_print" && arguments.empty()) { continue; } - if (dynamic_pointer_cast(cont) && ss == "unscoped") + if (dynamic_pointer_cast(cont) && directive == "cpp:unscoped" && arguments.empty()) { continue; } { ClassDeclPtr cl = dynamic_pointer_cast(cont); - if (cl && ss.find("type:") == 0) + if (cl && directive == "cpp:type" && !arguments.empty()) { continue; } } - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + s + "'"); - newMetadata.remove(s); + ostringstream ostr; + ostr << "ignoring invalid metadata '" << *meta << "'"; + dc->warning(InvalidMetadata, file, line, ostr.str()); + metadata.remove(meta); } - return newMetadata; + return metadata; } TypeContext Slice::Gen::setUseWstring(ContainedPtr p, list& hist, TypeContext typeCtx) { hist.push_back(typeCtx); - StringList metadata = p->getMetadata(); - if (find(metadata.begin(), metadata.end(), "cpp:type:wstring") != metadata.end()) - { - typeCtx = TypeContext::UseWstring; - } - else if (find(metadata.begin(), metadata.end(), "cpp:type:string") != metadata.end()) + if (auto argument = p->getMetadataArgs("cpp:type")) { - typeCtx = TypeContext::None; + if (argument == "wstring") + { + typeCtx = TypeContext::UseWstring; + } + else if (argument == "string") + { + typeCtx = TypeContext::None; + } } return typeCtx; } @@ -1213,27 +1219,17 @@ Slice::Gen::resetUseWstring(list& hist) string Slice::Gen::getHeaderExt(const string& file, const UnitPtr& ut) { - static const string headerExtPrefix = "cpp:header-ext:"; DefinitionContextPtr dc = ut->findDefinitionContext(file); assert(dc); - if (auto meta = dc->findMetadata(headerExtPrefix)) - { - return meta->substr(headerExtPrefix.size()); - } - return ""; + return dc->getMetadataArgs("cpp:header-ext").value_or(""); } string Slice::Gen::getSourceExt(const string& file, const UnitPtr& ut) { - static const string sourceExtPrefix = "cpp:source-ext:"; DefinitionContextPtr dc = ut->findDefinitionContext(file); assert(dc); - if (auto meta = dc->findMetadata(sourceExtPrefix)) - { - return meta->substr(sourceExtPrefix.size()); - } - return ""; + return dc->getMetadataArgs("cpp:source-ext").value_or(""); } Slice::Gen::ForwardDeclVisitor::ForwardDeclVisitor(Output& h) : H(h), _useWstring(TypeContext::None) {} @@ -1338,7 +1334,7 @@ Slice::Gen::ForwardDeclVisitor::visitSequence(const SequencePtr& p) string scope = fixKwd(p->scope()); TypePtr type = p->type(); TypeContext typeCtx = _useWstring; - StringList metadata = p->getMetadata(); + MetadataList metadata = p->getMetadata(); string seqType = findMetadata(metadata, _useWstring); writeDocSummary(H, p); @@ -1658,7 +1654,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) for (const auto& q : paramList) { string paramName = fixKwd(q->name()); - StringList metadata = q->getMetadata(); + MetadataList metadata = q->getMetadata(); if (q->isOutParam()) { @@ -2223,8 +2219,7 @@ Slice::Gen::DataDefVisitor::visitExceptionStart(const ExceptionPtr& p) H << sp; } - StringList metadata = p->getMetadata(); - if (find(metadata.begin(), metadata.end(), "cpp:ice_print") != metadata.end()) + if (p->hasMetadata("cpp:ice_print")) { H << nl << "/**"; H << nl << " * Outputs a custom description of this exception to a stream."; diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h index 0c66d86aa52..8409c5809dd 100644 --- a/cpp/src/slice2cpp/Gen.h +++ b/cpp/src/slice2cpp/Gen.h @@ -218,7 +218,7 @@ namespace Slice void visitConst(const ConstPtr&) final; private: - StringList validate(const SyntaxTreeBasePtr&, const StringList&, const std::string&, int, bool = false); + MetadataList validate(const SyntaxTreeBasePtr&, MetadataList, const std::string&, int, bool = false); }; static void validateMetadata(const UnitPtr&); diff --git a/cpp/src/slice2cpp/Main.cpp b/cpp/src/slice2cpp/Main.cpp index d015829bcdd..6f347f228e2 100644 --- a/cpp/src/slice2cpp/Main.cpp +++ b/cpp/src/slice2cpp/Main.cpp @@ -209,14 +209,9 @@ compile(const vector& argv) UnitPtr u = Unit::createUnit(false); int parseStatus = u->parse(*i, cppHandle, debug); - string ext = headerExtension; - static const string headerExtPrefix = "cpp:header-ext:"; DefinitionContextPtr dc = u->findDefinitionContext(u->topLevelFile()); assert(dc); - if (auto meta = dc->findMetadata(headerExtPrefix)) - { - ext = meta->substr(headerExtPrefix.size()); - } + string ext = dc->getMetadataArgs("cpp:header-ext").value_or(""); u->destroy(); diff --git a/cpp/src/slice2cs/CsUtil.cpp b/cpp/src/slice2cs/CsUtil.cpp index 9a619070cb6..eea19193cd8 100644 --- a/cpp/src/slice2cs/CsUtil.cpp +++ b/cpp/src/slice2cs/CsUtil.cpp @@ -80,12 +80,7 @@ Slice::CsGenerator::getNamespacePrefix(const ContainedPtr& cont) assert(m); - static const string prefix = "cs:namespace:"; - if (auto meta = m->findMetadata(prefix)) - { - return meta->substr(prefix.size()); - } - return ""; + return m->getMetadataArgs("cs:namespace").value_or(""); } string @@ -357,10 +352,9 @@ Slice::CsGenerator::typeToString(const TypePtr& type, const string& package, boo SequencePtr seq = dynamic_pointer_cast(type); if (seq) { - string prefix = "cs:generic:"; - if (auto meta = seq->findMetadata(prefix)) + if (auto metadata = seq->getMetadataArgs("cs:generic")) { - string customType = meta->substr(prefix.size()); + string customType = *metadata; if (customType == "List" || customType == "LinkedList" || customType == "Queue" || customType == "Stack") { return "global::System.Collections.Generic." + customType + "<" + typeToString(seq->type(), package) + @@ -378,16 +372,7 @@ Slice::CsGenerator::typeToString(const TypePtr& type, const string& package, boo DictionaryPtr d = dynamic_pointer_cast(type); if (d) { - string prefix = "cs:generic:"; - string typeName; - if (auto meta = d->findMetadata(prefix)) - { - typeName = meta->substr(prefix.size()); - } - else - { - typeName = "Dictionary"; - } + string typeName = d->getMetadataArgs("cs:generic").value_or("Dictionary"); return "global::System.Collections.Generic." + typeName + "<" + typeToString(d->keyType(), package) + ", " + typeToString(d->valueType(), package) + ">"; } @@ -1142,7 +1127,7 @@ Slice::CsGenerator::writeSequenceMarshalUnmarshalCode( assert(cont); if (useHelper) { - string helperName = getUnqualified(getNamespace(seq) + "." + seq->name() + "Helper", scope); + string helperName = getUnqualified(seq, scope, "", "Helper"); if (marshal) { out << nl << helperName << ".write(" << stream << ", " << param << ");"; @@ -1157,7 +1142,6 @@ Slice::CsGenerator::writeSequenceMarshalUnmarshalCode( TypePtr type = seq->type(); string typeS = typeToString(type, scope); - const string genericPrefix = "cs:generic:"; string genericType; string addMethod = "Add"; bool isGeneric = false; @@ -1165,10 +1149,10 @@ Slice::CsGenerator::writeSequenceMarshalUnmarshalCode( bool isList = false; bool isLinkedList = false; bool isCustom = false; - if (auto meta = seq->findMetadata(genericPrefix)) + if (auto metadata = seq->getMetadataArgs("cs:generic")) { isGeneric = true; - genericType = meta->substr(genericPrefix.size()); + genericType = *metadata; if (genericType == "LinkedList") { addMethod = "AddLast"; @@ -1785,7 +1769,7 @@ Slice::CsGenerator::writeOptionalSequenceMarshalUnmarshalCode( const string typeS = typeToString(type, scope); const string seqS = typeToString(seq, scope); - const bool isArray = !seq->hasMetadata("cs:generic:"); + const bool isArray = !seq->hasMetadata("cs:generic"); const string length = isArray ? param + ".Length" : param + ".Count"; BuiltinPtr builtin = dynamic_pointer_cast(type); @@ -1989,28 +1973,21 @@ Slice::CsGenerator::MetadataVisitor::visitUnitStart(const UnitPtr& unit) { DefinitionContextPtr dc = unit->findDefinitionContext(file); assert(dc); - StringList fileMetadata = dc->getMetadata(); - StringList newFileMetadata; - static const string csPrefix = "cs:"; - for (StringList::iterator r = fileMetadata.begin(); r != fileMetadata.end(); ++r) + MetadataList newFileMetadata; + for (const auto& metadata : dc->getMetadata()) { - string& s = *r; - string oldS = s; - - if (s.find(csPrefix) == 0) + string_view directive = metadata->directive(); + if (directive.find("cs:") == 0 && directive != "cs:attribute") { - static const string csAttributePrefix = csPrefix + "attribute:"; - if (!(s.find(csAttributePrefix) == 0 && s.size() > csAttributePrefix.size())) - { - dc->warning(InvalidMetadata, file, -1, "ignoring invalid file metadata `" + oldS + "'"); - continue; - } + ostringstream msg; + msg << "ignoring invalid file metadata '" << *metadata << "'"; + dc->warning(InvalidMetadata, file, -1, msg.str()); + continue; } - newFileMetadata.push_back(oldS); + newFileMetadata.push_back(metadata); } - - dc->setMetadata(newFileMetadata); + dc->setMetadata(std::move(newFileMetadata)); } return true; } @@ -2053,11 +2030,9 @@ void Slice::CsGenerator::MetadataVisitor::visitOperation(const OperationPtr& p) { validate(p); - - ParamDeclList params = p->parameters(); - for (ParamDeclList::const_iterator i = params.begin(); i != params.end(); ++i) + for (const auto& param : p->parameters()) { - visitParamDecl(*i); + visitParamDecl(param); } } @@ -2100,90 +2075,74 @@ Slice::CsGenerator::MetadataVisitor::visitConst(const ConstPtr& p) void Slice::CsGenerator::MetadataVisitor::validate(const ContainedPtr& cont) { - const string msg = "ignoring invalid metadata"; - - StringList localMetadata = cont->getMetadata(); - StringList newLocalMetadata; - const UnitPtr ut = cont->unit(); const DefinitionContextPtr dc = ut->findDefinitionContext(cont->file()); assert(dc); - for (StringList::iterator p = localMetadata.begin(); p != localMetadata.end(); ++p) + MetadataList newLocalMetadata; + for (const auto& metadata : cont->getMetadata()) { - string& s = *p; - string oldS = s; + string_view directive = metadata->directive(); + string_view arguments = metadata->arguments(); - const string csPrefix = "cs:"; - if (s.find(csPrefix) == 0) + if (directive.find("cs:") == 0) { SequencePtr seq = dynamic_pointer_cast(cont); if (seq) { - static const string csGenericPrefix = csPrefix + "generic:"; - if (s.find(csGenericPrefix) == 0) + if (directive == "cs:generic") { - string type = s.substr(csGenericPrefix.size()); - if (type == "LinkedList" || type == "Queue" || type == "Stack") + if (arguments == "LinkedList" || arguments == "Queue" || arguments == "Stack") { if (!seq->type()->isClassType()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } } - else if (!type.empty()) + else if (!arguments.empty()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; // Custom type or List } } } else if (dynamic_pointer_cast(cont)) { - if (s.substr(csPrefix.size()) == "class") - { - newLocalMetadata.push_back(s); - continue; - } - if (s.substr(csPrefix.size()) == "property") + if ((directive == "cs:class" || directive == "cs:property") && arguments.empty()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } - static const string csImplementsPrefix = csPrefix + "implements:"; - if (s.find(csImplementsPrefix) == 0) + if (directive == "cs:implements" && !arguments.empty()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } } else if (dynamic_pointer_cast(cont) || dynamic_pointer_cast(cont)) { - if (s.substr(csPrefix.size()) == "property") + if (directive == "cs:property" && arguments.empty()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } } else if (dynamic_pointer_cast(cont)) { - static const string csImplementsPrefix = csPrefix + "implements:"; - if (s.find(csImplementsPrefix) == 0) + if (directive == "cs:implements" && !arguments.empty()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } } else if (dynamic_pointer_cast(cont)) { - static const string csGenericPrefix = csPrefix + "generic:"; - if (s.find(csGenericPrefix) == 0) + if (directive == "cs:generic") { - string type = s.substr(csGenericPrefix.size()); - if (type == "SortedDictionary" || type == "SortedList") + if (arguments == "SortedDictionary" || arguments == "SortedList") { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } } @@ -2194,30 +2153,31 @@ Slice::CsGenerator::MetadataVisitor::validate(const ContainedPtr& cont) StructPtr st = dynamic_pointer_cast(dataMember->container()); ExceptionPtr ex = dynamic_pointer_cast(dataMember->container()); ClassDefPtr cl = dynamic_pointer_cast(dataMember->container()); - static const string csTypePrefix = csPrefix + "type:"; + static const string csTypePrefix = "cs:type:"; + // TODO Seems like this validation only got half written?... } else if (dynamic_pointer_cast(cont)) { - static const string csNamespacePrefix = csPrefix + "namespace:"; - if (s.find(csNamespacePrefix) == 0 && s.size() > csNamespacePrefix.size()) + if (directive == "cs:namespace" && !arguments.empty()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } } - static const string csAttributePrefix = csPrefix + "attribute:"; - if (s.find(csAttributePrefix) == 0 && s.size() > csAttributePrefix.size()) + if (directive == "cs:attribute" && !arguments.empty()) { - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); continue; } - dc->warning(InvalidMetadata, cont->file(), cont->line(), msg + " `" + oldS + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *metadata << "'"; + dc->warning(InvalidMetadata, cont->file(), cont->line(), msg.str()); continue; } - newLocalMetadata.push_back(s); + newLocalMetadata.push_back(metadata); } - cont->setMetadata(newLocalMetadata); + cont->setMetadata(std::move(newLocalMetadata)); } diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 6466420b29f..5979c435126 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -403,17 +403,15 @@ Slice::CsVisitor::writeMarshaling(const ClassDefPtr& p) string Slice::CsVisitor::getParamAttributes(const ParamDeclPtr& p) { - string result; - StringList metadata = p->getMetadata(); - for (StringList::const_iterator i = metadata.begin(); i != metadata.end(); ++i) + ostringstream ostr; + for (const auto& metadata : p->getMetadata()) { - static const string prefix = "cs:attribute:"; - if (i->find(prefix) == 0) + if (metadata->directive() == "cs:attribute") { - result += "[" + i->substr(prefix.size()) + "] "; + ostr << "[" << metadata->arguments() << "] "; } } - return result; + return ostr.str(); } vector @@ -558,13 +556,11 @@ Slice::CsVisitor::getDispatchParams( void Slice::CsVisitor::emitAttributes(const ContainedPtr& p) { - StringList metadata = p->getMetadata(); - for (StringList::const_iterator i = metadata.begin(); i != metadata.end(); ++i) + for (const auto& metadata : p->getMetadata()) { - static const string prefix = "cs:attribute:"; - if (i->find(prefix) == 0) + if (metadata->directive() == "cs:attribute") { - _out << nl << '[' << i->substr(prefix.size()) << ']'; + _out << nl << '[' << metadata->arguments() << ']'; } } } @@ -1459,21 +1455,17 @@ Slice::Gen::UnitVisitor::visitUnitStart(const UnitPtr& unit) DefinitionContextPtr dc = unit->findDefinitionContext(unit->topLevelFile()); assert(dc); - static const string attributePrefix = "cs:attribute:"; - bool sep = false; for (const auto& metadata : dc->getMetadata()) { - string::size_type pos = metadata.find(attributePrefix); - if (pos == 0 && metadata.size() > attributePrefix.size()) + if (metadata->directive() == "cs:attribute") { if (!sep) { _out << sp; sep = true; } - string attrib = metadata.substr(pos + attributePrefix.size()); - _out << nl << '[' << attrib << ']'; + _out << nl << '[' << metadata->arguments() << ']'; } } return false; @@ -1665,7 +1657,7 @@ Slice::Gen::TypesVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) string ns = getNamespace(p); InterfaceList bases = p->bases(); - StringList baseNames; + list baseNames; _out << sp; emitAttributes(p); @@ -1683,27 +1675,25 @@ Slice::Gen::TypesVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) baseNames.push_back("Ice.Object"); } - // - // Check for cs:implements metadata. - // - const StringList metadata = p->getMetadata(); - static const string prefix = "cs:implements:"; - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + // Check for `cs:implements` metadata. + for (const auto& metadata : p->getMetadata()) { - if (q->find(prefix) == 0) + if (metadata->directive() == "cs:implements") { - baseNames.push_back(q->substr(prefix.size())); + baseNames.push_back(string{metadata->arguments()}); } } _out << " : "; - for (StringList::const_iterator q = baseNames.begin(); q != baseNames.end(); ++q) + bool emitSep = false; + for (const auto& baseName : baseNames) { - if (q != baseNames.begin()) + if (emitSep) { _out << ", "; } - _out << *q; + emitSep = true; + _out << baseName; } _out << sb; @@ -1956,30 +1946,28 @@ Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) emitAttributes(p); _out << nl << "public " << (classMapping ? "sealed partial record class" : "partial record struct") << ' ' << name; - // // Check for cs:implements metadata. - // - StringList baseNames; - const StringList metadata = p->getMetadata(); - static const string prefix = "cs:implements:"; - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + list baseNames; + for (const auto& metadata : p->getMetadata()) { - if (q->find(prefix) == 0) + if (metadata->directive() == "cs:implements") { - baseNames.push_back(q->substr(prefix.size())); + baseNames.push_back(string{metadata->arguments()}); } } if (!baseNames.empty()) { _out << " : "; - for (StringList::const_iterator q = baseNames.begin(); q != baseNames.end(); ++q) + bool emitSep = false; + for (const auto& baseName : baseNames) { - if (q != baseNames.begin()) + if (emitSep) { _out << ", "; } - _out << getUnqualified(*q, ns); + emitSep = true; + _out << getUnqualified(baseName, ns); } } @@ -3101,10 +3089,9 @@ Slice::Gen::HelperVisitor::visitSequence(const SequencePtr& p) _out << eb; _out << eb; - string prefix = "cs:generic:"; - if (auto meta = p->findMetadata(prefix)) + if (auto metadata = p->getMetadataArgs("cs:generic")) { - string type = meta->substr(prefix.size()); + string_view type = *metadata; if (type == "List" || type == "LinkedList" || type == "Queue" || type == "Stack") { return; @@ -3138,16 +3125,7 @@ Slice::Gen::HelperVisitor::visitDictionary(const DictionaryPtr& p) TypePtr key = p->keyType(); TypePtr value = p->valueType(); - string prefix = "cs:generic:"; - string genericType; - if (auto meta = p->findMetadata(prefix)) - { - genericType = meta->substr(prefix.size()); - } - else - { - genericType = "Dictionary"; - } + string genericType = p->getMetadataArgs("cs:generic").value_or("Dictionary"); string ns = getNamespace(p); string keyS = typeToString(key, ns); diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp index aabe6a5385a..19e5436405b 100644 --- a/cpp/src/slice2java/Gen.cpp +++ b/cpp/src/slice2java/Gen.cpp @@ -1004,7 +1004,7 @@ Slice::JavaVisitor::writeUnmarshalProxyResults(Output& out, const string& packag bool optional; TypePtr type; int tag; - StringList metadata; + MetadataList metadata; if (ret) { type = ret; @@ -1102,7 +1102,7 @@ Slice::JavaVisitor::writeMarshalServantResults( OptionalMode mode; TypePtr type; int tag; - StringList metadata; + MetadataList metadata; if (op->returnType()) { type = op->returnType(); @@ -1343,18 +1343,11 @@ Slice::JavaVisitor::writeDispatch(Output& out, const InterfaceDefPtr& p) out << nl << "return \"" << p->scoped() << "\";"; out << eb; - // // Dispatch methods. We only generate methods for operations // defined in this InterfaceDef, because we reuse existing methods // for inherited operations. - // - for (OperationList::const_iterator r = ops.begin(); r != ops.end(); ++r) + for (const auto& op : ops) { - OperationPtr op = *r; - StringList opMetadata = op->getMetadata(); - - CommentPtr dc = op->parseComment(false); - string opName = op->name(); out << sp; @@ -2319,17 +2312,13 @@ Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p) Output& out = output(); - // - // Check for java:implements metadata. - // - const StringList metadata = p->getMetadata(); - static const string prefix = "java:implements:"; + // Check for 'java:implements' metadata. StringList implements; - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + for (const auto& metadata : p->getMetadata()) { - if (q->find(prefix) == 0) + if (metadata->directive() == "java:implements") { - implements.push_back(q->substr(prefix.size())); + implements.push_back(string{metadata->arguments()}); } } @@ -2938,17 +2927,13 @@ Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) Output& out = output(); - // - // Check for java:implements metadata. - // - const StringList metadata = p->getMetadata(); - static const string prefix = "java:implements:"; + // Check for 'java:implements' metadata. StringList implements; - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + for (const auto& metadata : p->getMetadata()) { - if (q->find(prefix) == 0) + if (metadata->directive() == "java:implements") { - implements.push_back(q->substr(prefix.size())); + implements.push_back(string{metadata->arguments()}); } } @@ -3259,13 +3244,13 @@ Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p) const ContainedPtr contained = dynamic_pointer_cast(container); const string name = fixKwd(p->name()); - const StringList metadata = p->getMetadata(); - const bool getSet = p->hasMetadata(_getSetMetadata) || contained->hasMetadata(_getSetMetadata); + const bool getSet = p->hasMetadata("java:getset") || contained->hasMetadata("java:getset"); const bool optional = p->optional(); const TypePtr type = p->type(); const BuiltinPtr b = dynamic_pointer_cast(type); const bool classType = type->isClassType(); + const MetadataList metadata = p->getMetadata(); const string s = typeToString(type, TypeModeMember, getPackage(contained), metadata, true, false); Output& out = output(); @@ -3279,10 +3264,8 @@ Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p) out << nl << "@Deprecated"; } - // // Access visibility for class data members can be controlled by metadata. // If none is specified, the default is public. - // if (cls && (p->hasMetadata("protected") || contained->hasMetadata("protected"))) { out << nl << "protected " << s << ' ' << name << ';'; @@ -3496,7 +3479,7 @@ Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p) if (!hasTypeMetadata(seq, metadata)) { string elem = - typeToString(seq->type(), TypeModeMember, getPackage(contained), StringList(), true, false); + typeToString(seq->type(), TypeModeMember, getPackage(contained), MetadataList(), true, false); // // Indexed getter. @@ -3783,7 +3766,7 @@ Slice::Gen::HelperVisitor::visitSequence(const SequencePtr& p) bool suppressUnchecked = false; string instanceType, formalType; - bool customType = getSequenceTypes(p, "", StringList(), instanceType, formalType); + bool customType = getSequenceTypes(p, "", MetadataList(), instanceType, formalType); if (!customType) { @@ -3876,16 +3859,13 @@ Slice::Gen::HelperVisitor::visitSequence(const SequencePtr& p) } else { - // // The sequence is an instance of java.util.List, where E is a fixed-size type. // If the element type is bool or byte, we do NOT write an extra size. - // const size_t sz = p->type()->minWireSize(); if (sz > 1) { - string metadata; out << nl << "final int optSize = v == null ? 0 : "; - if (findMetadata("java:buffer", p->getMetadata(), metadata)) + if (p->hasMetadata("java:buffer")) { out << "v.remaining() / " << sz << ";"; } @@ -3949,8 +3929,7 @@ Slice::Gen::HelperVisitor::visitDictionary(const DictionaryPtr& p) string absolute = getUnqualified(p); string helper = getUnqualified(p, "", "", "Helper"); string package = getPackage(p); - StringList metadata = p->getMetadata(); - string formalType = typeToString(p, TypeModeIn, package, StringList(), true); + string formalType = typeToString(p, TypeModeIn, package, MetadataList(), true); open(helper, p->file()); Output& out = output(); diff --git a/cpp/src/slice2java/JavaUtil.cpp b/cpp/src/slice2java/JavaUtil.cpp index 94e8d1f35e9..a073dfad9dc 100644 --- a/cpp/src/slice2java/JavaUtil.cpp +++ b/cpp/src/slice2java/JavaUtil.cpp @@ -82,85 +82,84 @@ namespace public: bool visitUnitStart(const UnitPtr& unit) final { - static const string prefix = "java:"; - // Validate file metadata in the top-level file and all included files. for (const auto& file : unit->allFiles()) { DefinitionContextPtr dc = unit->findDefinitionContext(file); assert(dc); - StringList fileMetadata = dc->getMetadata(); - for (StringList::const_iterator r = fileMetadata.begin(); r != fileMetadata.end();) + MetadataList fileMetadata = dc->getMetadata(); + for (MetadataList::const_iterator r = fileMetadata.begin(); r != fileMetadata.end();) { - string s = *r++; - if (s.find(prefix) == 0) + MetadataPtr metadata = *r++; + const string_view directive = metadata->directive(); + if (directive.find("java:") == 0) { - static const string packagePrefix = "java:package:"; - if (s.find(packagePrefix) == 0 && s.size() > packagePrefix.size()) + if (directive == "java:package" && !metadata->arguments().empty()) { continue; } else { - dc->warning(InvalidMetadata, file, -1, "ignoring invalid file metadata `" + s + "'"); - fileMetadata.remove(s); - continue; + ostringstream msg; + msg << "ignoring invalid file metadata '" << *metadata << "'"; + dc->warning(InvalidMetadata, file, -1, msg.str()); + fileMetadata.remove(metadata); } - }; + } } - dc->setMetadata(fileMetadata); + dc->setMetadata(std::move(fileMetadata)); } return true; } bool visitModuleStart(const ModulePtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); return true; } void visitClassDecl(const ClassDeclPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); } bool visitClassDefStart(const ClassDefPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); return true; } bool visitExceptionStart(const ExceptionPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); return true; } bool visitStructStart(const StructPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); return true; } void visitOperation(const OperationPtr& p) final { TypePtr returnType = p->returnType(); - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); UnitPtr unt = p->unit(); string file = p->file(); @@ -168,17 +167,15 @@ namespace if (!returnType) { - for (StringList::const_iterator q = metadata.begin(); q != metadata.end();) + for (MetadataList::const_iterator q = metadata.begin(); q != metadata.end();) { - string s = *q++; - if (s.find("java:type:", 0) == 0) + MetadataPtr m = *q++; + if (m->directive() == "java:type") { - dc->warning( - InvalidMetadata, - p->file(), - p->line(), - "ignoring invalid metadata `" + s + "' for operation with void return type"); - metadata.remove(s); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "' for operation with void return type"; + dc->warning(InvalidMetadata, m->file(), m->line(), msg.str()); + metadata.remove(m); continue; } } @@ -186,197 +183,182 @@ namespace else { metadata = validateType(returnType, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); + metadata = validateGetSet(p, metadata); } - p->setMetadata(metadata); + p->setMetadata(std::move(metadata)); - ParamDeclList params = p->parameters(); - for (ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) + for (const auto& param : p->parameters()) { - metadata = getMetadata(*q); - metadata = validateType((*q)->type(), metadata, p->file(), (*q)->line()); - metadata = validateGetSet((*q)->type(), metadata, p->file(), (*q)->line()); - (*q)->setMetadata(metadata); + metadata = getMetadata(param); + metadata = validateType(param->type(), metadata, param->file(), param->line()); + metadata = validateGetSet(param, metadata); + param->setMetadata(std::move(metadata)); } } void visitDataMember(const DataMemberPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p->type(), metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); } void visitSequence(const SequencePtr& p) final { - static const string serializable = "java:serializable:"; - static const string bytebuffer = "java:buffer"; - StringList metadata = getMetadata(p); - StringList newMetadata; + MetadataList metadata = getMetadata(p); + MetadataList newMetadata; const string file = p->file(); int line = p->line(); const UnitPtr unt = p->unit(); const DefinitionContextPtr dc = unt->findDefinitionContext(file); - for (StringList::const_iterator q = metadata.begin(); q != metadata.end();) + for (MetadataList::const_iterator q = metadata.begin(); q != metadata.end();) { - string s = *q++; + MetadataPtr m = *q++; - if (s.find(serializable) == 0) + if (m->directive() == "java:serializable") { - // // Remove from list so validateType does not try to handle as well. - // - metadata.remove(s); + metadata.remove(m); BuiltinPtr builtin = dynamic_pointer_cast(p->type()); if (!builtin || builtin->kind() != Builtin::KindByte) { - dc->warning( - InvalidMetadata, - file, - line, - "ignoring invalid metadata `" + s + - "': " + "this metadata can only be used with a byte sequence"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m + << "': this metadata can only be used with a byte sequence"; + dc->warning(InvalidMetadata, file, line, msg.str()); continue; } - newMetadata.push_back(s); + newMetadata.push_back(m); } - else if (s.find(bytebuffer) == 0) + else if (m->directive() == "java:buffer") { - metadata.remove(s); + metadata.remove(m); BuiltinPtr builtin = dynamic_pointer_cast(p->type()); if (!builtin || (builtin->kind() != Builtin::KindByte && builtin->kind() != Builtin::KindShort && builtin->kind() != Builtin::KindInt && builtin->kind() != Builtin::KindLong && builtin->kind() != Builtin::KindFloat && builtin->kind() != Builtin::KindDouble)) { - dc->warning( - InvalidMetadata, - file, - line, - "ignoring invalid metadata `" + s + "': " + "this metadata can not be used with this type"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "': this metadata can not be used with this type"; + dc->warning(InvalidMetadata, file, line, msg.str()); continue; } - newMetadata.push_back(s); + newMetadata.push_back(m); } } metadata = validateType(p, metadata, file, line); - metadata = validateGetSet(p, metadata, file, line); + metadata = validateGetSet(p, metadata); newMetadata.insert(newMetadata.begin(), metadata.begin(), metadata.end()); - p->setMetadata(newMetadata); + p->setMetadata(std::move(newMetadata)); } void visitDictionary(const DictionaryPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); } void visitEnum(const EnumPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); } void visitConst(const ConstPtr& p) final { - StringList metadata = getMetadata(p); + MetadataList metadata = getMetadata(p); metadata = validateType(p, metadata, p->file(), p->line()); - metadata = validateGetSet(p, metadata, p->file(), p->line()); - p->setMetadata(metadata); + metadata = validateGetSet(p, metadata); + p->setMetadata(std::move(metadata)); } bool shouldVisitIncludedDefinitions() const final { return true; } private: - StringList getMetadata(const ContainedPtr& cont) + MetadataList getMetadata(const ContainedPtr& cont) { - static const string prefix = "java:"; - - StringList metadata = cont->getMetadata(); - StringList result; + MetadataList result; UnitPtr unt = cont->container()->unit(); string file = cont->file(); DefinitionContextPtr dc = unt->findDefinitionContext(file); assert(dc); - for (StringList::const_iterator p = metadata.begin(); p != metadata.end(); ++p) + for (const auto& m : cont->getMetadata()) { - string s = *p; - if (s.find(prefix) == 0) + const string_view directive = m->directive(); + if (directive.find("java:") == 0) { - string::size_type pos = s.find(':', prefix.size()); - if (pos == string::npos) + if (m->arguments().empty()) { - if (s.size() > prefix.size()) + if (directive == "java:getset") + { + result.push_back(m); + continue; + } + else if (directive == "java:buffer") + { + result.push_back(m); + continue; + } + else if (directive == "java:tie") + { + result.push_back(m); + continue; + } + else if (directive == "java:UserException") { - string rest = s.substr(prefix.size()); - if (rest == "getset") - { - result.push_back(s); - continue; - } - else if (rest == "buffer") - { - result.push_back(s); - continue; - } - else if (rest == "tie") - { - result.push_back(s); - continue; - } - else if (rest == "UserException") - { - result.push_back(s); - continue; - } - else if (rest == "optional") - { - result.push_back(s); - continue; - } + result.push_back(m); + continue; + } + else if (directive == "java:optional") + { + result.push_back(m); + continue; } } - else if (s.substr(prefix.size(), pos - prefix.size()) == "type") + else if (directive == "java:type") { - result.push_back(s); + result.push_back(m); continue; } - else if (s.substr(prefix.size(), pos - prefix.size()) == "serializable") + else if (directive == "java:serializable") { - result.push_back(s); + result.push_back(m); continue; } - else if (s.substr(prefix.size(), pos - prefix.size()) == "serialVersionUID") + else if (directive == "java:serialVersionUID") { - result.push_back(s); + result.push_back(m); continue; } - else if (s.substr(prefix.size(), pos - prefix.size()) == "implements") + else if (directive == "java:implements") { - result.push_back(s); + result.push_back(m); continue; } - else if (s.substr(prefix.size(), pos - prefix.size()) == "package") + else if (directive == "java:package") { - result.push_back(s); + result.push_back(m); continue; } - dc->warning(InvalidMetadata, cont->file(), cont->line(), "ignoring invalid metadata `" + s + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "'"; + dc->warning(InvalidMetadata, m->file(), m->line(), msg.str()); } else { - result.push_back(s); + result.push_back(m); continue; } } @@ -384,18 +366,20 @@ namespace return result; } - StringList validateType(const SyntaxTreeBasePtr& p, const StringList& metadata, const string& file, int line) + MetadataList + validateType(const SyntaxTreeBasePtr& p, const MetadataList& metadata, const string& file, int line) { const UnitPtr unt = p->unit(); const DefinitionContextPtr dc = unt->findDefinitionContext(file); assert(dc); - StringList newMetadata; - for (StringList::const_iterator i = metadata.begin(); i != metadata.end(); ++i) + + MetadataList newMetadata; + for (const auto& m : metadata) { - // + const string_view directive = m->directive(); + // Type metadata ("java:type:Foo") is only supported by sequences and dictionaries. - // - if (i->find("java:type:", 0) == 0 && + if (directive == "java:type" && (!dynamic_pointer_cast(p) && !dynamic_pointer_cast(p))) { string str; @@ -410,9 +394,11 @@ namespace assert(b); str = b->typeId(); } - dc->warning(InvalidMetadata, file, line, "invalid metadata for " + str); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "' for " << str; + dc->warning(InvalidMetadata, file, line, msg.str()); } - else if (i->find("java:buffer") == 0) + else if (directive == "java:buffer") { SequencePtr seq = dynamic_pointer_cast(p); if (seq) @@ -423,86 +409,75 @@ namespace builtin->kind() == Builtin::KindInt || builtin->kind() == Builtin::KindLong || builtin->kind() == Builtin::KindFloat || builtin->kind() == Builtin::KindDouble)) { - newMetadata.push_back(*i); + newMetadata.push_back(m); continue; } } - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + *i + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "'"; + dc->warning(InvalidMetadata, file, line, msg.str()); } - else if (i->find("java:serializable:") == 0) + else if (directive == "java:serializable") { - // // Only valid in sequence definition which is checked in visitSequence - // - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + *i + "'"); - } - else if (i->find("delegate") == 0) - { - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + *i + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "'"; + dc->warning(InvalidMetadata, file, line, msg.str()); } - else if (i->find("java:implements:") == 0) + else if (directive == "java:implements") { if (dynamic_pointer_cast(p) || dynamic_pointer_cast(p)) { - newMetadata.push_back(*i); + newMetadata.push_back(m); } else { - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + *i + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "'"; + dc->warning(InvalidMetadata, file, line, msg.str()); } } - else if (i->find("java:package:") == 0) + else if (directive == "java:package") { - ModulePtr m = dynamic_pointer_cast(p); - if (m && dynamic_pointer_cast(m->container())) + ModulePtr mod = dynamic_pointer_cast(p); + if (mod && dynamic_pointer_cast(mod->container())) { - newMetadata.push_back(*i); + newMetadata.push_back(m); } else { - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + *i + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *m << "'"; + dc->warning(InvalidMetadata, file, line, msg.str()); } } else { - newMetadata.push_back(*i); + newMetadata.push_back(m); } } return newMetadata; } - StringList validateGetSet(const SyntaxTreeBasePtr& p, const StringList& metadata, const string& file, int line) + MetadataList validateGetSet(const ContainedPtr& p, const MetadataList& metadata) { const UnitPtr unt = p->unit(); - const DefinitionContextPtr dc = unt->findDefinitionContext(file); + const DefinitionContextPtr dc = unt->findDefinitionContext(p->file()); assert(dc); - StringList newMetadata; - for (StringList::const_iterator i = metadata.begin(); i != metadata.end(); ++i) + + MetadataList newMetadata; + for (const auto& m : metadata) { - // // The "getset" metadata can only be specified on a class, struct, exception or data member. - // - if ((*i) == "java:getset" && + if (m->directive() == "java:getset" && (!dynamic_pointer_cast(p) && !dynamic_pointer_cast(p) && !dynamic_pointer_cast(p) && !dynamic_pointer_cast(p))) { - string str; - ContainedPtr cont = dynamic_pointer_cast(p); - if (cont) - { - str = cont->kindOf(); - } - else - { - BuiltinPtr b = dynamic_pointer_cast(p); - assert(b); - str = b->typeId(); - } - dc->warning(InvalidMetadata, file, line, "invalid metadata for " + str); + dc->warning(InvalidMetadata, m->file(), m->line(), "invalid metadata for " + p->kindOf()); continue; } - newMetadata.push_back(*i); + newMetadata.push_back(m); } return newMetadata; } @@ -515,11 +490,10 @@ Slice::getSerialVersionUID(const ContainedPtr& p) optional serialVersionUID = nullopt; // Check if the user provided their own UID value with metadata. - if (auto meta = p->findMetadata("java:serialVersionUID")) + if (auto meta = p->getMetadataArgs("java:serialVersionUID")) { string value = *meta; - string::size_type pos = value.rfind(":") + 1; - if (pos == string::npos) + if (value.empty()) { ostringstream os; os << "missing serialVersionUID value for " << p->kindOf() << " `" << p->scoped() @@ -531,7 +505,6 @@ Slice::getSerialVersionUID(const ContainedPtr& p) { try { - value = value.substr(pos); serialVersionUID = std::stoll(value, nullptr, 0); } catch (const std::exception&) @@ -752,8 +725,6 @@ Slice::JavaOutput::printHeader() print("//\n"); } -const string Slice::JavaGenerator::_getSetMetadata = "java:getset"; - Slice::JavaGenerator::JavaGenerator(const string& dir) : _dir(dir), _out(0) {} Slice::JavaGenerator::~JavaGenerator() @@ -903,26 +874,16 @@ Slice::JavaGenerator::getPackagePrefix(const ContainedPtr& cont) const assert(m); - // - // The java:package metadata can be defined as file metadata or applied to a top-level module. + // The 'java:package' metadata can be defined as file metadata or applied to a top-level module. // We check for the metadata at the top-level module first and then fall back to the global scope. - // - static const string prefix = "java:package:"; - - if (auto meta = m->findMetadata(prefix)) + if (auto metadataArgs = m->getMetadataArgs("java:package")) { - return meta->substr(prefix.size()); + return *metadataArgs; } - string file = cont->file(); DefinitionContextPtr dc = cont->unit()->findDefinitionContext(file); assert(dc); - if (auto meta = dc->findMetadata(prefix)) - { - return meta->substr(prefix.size()); - } - - return ""; + return dc->getMetadataArgs("java:package").value_or(""); } string @@ -1088,7 +1049,7 @@ Slice::JavaGenerator::typeToString( const TypePtr& type, TypeMode mode, const string& package, - const StringList& metadata, + const MetadataList& metadata, bool formal, bool optional) const { @@ -1217,7 +1178,7 @@ Slice::JavaGenerator::typeToObjectString( const TypePtr& type, TypeMode mode, const string& package, - const StringList& metadata, + const MetadataList& metadata, bool formal) const { static const char* builtinTable[] = { @@ -1254,7 +1215,7 @@ Slice::JavaGenerator::writeMarshalUnmarshalCode( bool marshal, int& iter, const string& customStream, - const StringList& metadata, + const MetadataList& metadata, const string& patchParams) { string stream = customStream; @@ -1405,7 +1366,7 @@ Slice::JavaGenerator::writeMarshalUnmarshalCode( { string instanceType, formalType, origInstanceType, origFormalType; getDictionaryTypes(dict, "", metadata, instanceType, formalType); - getDictionaryTypes(dict, "", StringList(), origInstanceType, origFormalType); + getDictionaryTypes(dict, "", MetadataList(), origInstanceType, origFormalType); if (formalType == origFormalType && (marshal || instanceType == origInstanceType)) { // @@ -1524,7 +1485,6 @@ Slice::JavaGenerator::writeMarshalUnmarshalCode( { if (optionalParam || mode == OptionalMember) { - string ignored; TypePtr elemType = seq->type(); BuiltinPtr eltBltin = dynamic_pointer_cast(elemType); if (!hasTypeMetadata(seq, metadata) && eltBltin && eltBltin->kind() < Builtin::KindObject) @@ -1556,12 +1516,11 @@ Slice::JavaGenerator::writeMarshalUnmarshalCode( } } else if ( - !hasTypeMetadata(seq, metadata) || seq->hasMetadata("java:type") || - findMetadata("java:type", metadata, ignored)) + !hasTypeMetadata(seq, metadata) || seq->hasMetadata("java:type") || hasMetadata("java:type", metadata)) { string instanceType, formalType, origInstanceType, origFormalType; getSequenceTypes(seq, "", metadata, instanceType, formalType); - getSequenceTypes(seq, "", StringList(), origInstanceType, origFormalType); + getSequenceTypes(seq, "", MetadataList(), origInstanceType, origFormalType); if (formalType == origFormalType && (marshal || instanceType == origInstanceType)) { string helper = getUnqualified(seq, package, "", "Helper"); @@ -1608,9 +1567,8 @@ Slice::JavaGenerator::writeMarshalUnmarshalCode( string s = optionalParam && optionalMapping ? param + ".get()" : param; if (sz > 1) { - string ignored2; out << nl << "final int optSize = " << s << " == null ? 0 : "; - if (seq->hasMetadata("java:buffer") || findMetadata("java:buffer", metadata, ignored2)) + if (seq->hasMetadata("java:buffer") || hasMetadata("java:buffer", metadata)) { out << s << ".remaining() / " << sz << ";"; } @@ -1712,7 +1670,7 @@ Slice::JavaGenerator::writeDictionaryMarshalUnmarshalCode( int& iter, bool useHelper, const string& customStream, - const StringList& metadata) + const MetadataList& metadata) { string stream = customStream; if (stream.empty()) @@ -1738,7 +1696,7 @@ Slice::JavaGenerator::writeDictionaryMarshalUnmarshalCode( // string instanceType, formalType, origInstanceType, origFormalType; getDictionaryTypes(dict, "", metadata, instanceType, formalType); - getDictionaryTypes(dict, "", StringList(), origInstanceType, origFormalType); + getDictionaryTypes(dict, "", MetadataList(), origInstanceType, origFormalType); if (useHelper && formalType == origFormalType && (marshal || instanceType == origInstanceType)) { // @@ -1826,7 +1784,7 @@ Slice::JavaGenerator::writeDictionaryMarshalUnmarshalCode( false, iter, customStream, - StringList(), + MetadataList(), patchParams.str()); } else @@ -1853,7 +1811,7 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode( int& iter, bool useHelper, const string& customStream, - const StringList& metadata) + const MetadataList& metadata) { string stream = customStream; if (stream.empty()) @@ -1871,8 +1829,7 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode( BuiltinPtr builtin = dynamic_pointer_cast(seq->type()); if (builtin && builtin->kind() == Builtin::KindByte) { - static const string serializable = "java:serializable:"; - if (seq->hasMetadata(serializable)) + if (seq->hasMetadata("java:serializable")) { if (marshal) { @@ -1892,9 +1849,8 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode( builtin->kind() == Builtin::KindInt || builtin->kind() == Builtin::KindLong || builtin->kind() == Builtin::KindFloat || builtin->kind() == Builtin::KindDouble)) { - string meta; static const string bytebuffer = "java:buffer"; - if (seq->hasMetadata(bytebuffer) || findMetadata(bytebuffer, metadata, meta)) + if (seq->hasMetadata(bytebuffer) || hasMetadata(bytebuffer, metadata)) { if (marshal) { @@ -1937,7 +1893,7 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode( // string instanceType, formalType, origInstanceType, origFormalType; bool customType = getSequenceTypes(seq, "", metadata, instanceType, formalType); - getSequenceTypes(seq, "", StringList(), origInstanceType, origFormalType); + getSequenceTypes(seq, "", MetadataList(), origInstanceType, origFormalType); if (useHelper && formalType == origFormalType && (marshal || instanceType == origInstanceType)) { // @@ -2037,7 +1993,7 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode( false, iter, customStream, - StringList(), + MetadataList(), patchParams.str()); } else @@ -2274,7 +2230,7 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode( false, iter, customStream, - StringList(), + MetadataList(), patchParams.str()); } else @@ -2299,13 +2255,12 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode( } bool -Slice::JavaGenerator::findMetadata(const string& prefix, const StringList& metadata, string& value) +Slice::JavaGenerator::hasMetadata(const string& directive, const MetadataList& metadata) { - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + for (const auto& m : metadata) { - if (q->find(prefix) == 0) + if (m->directive() == directive) { - value = *q; return true; } } @@ -2314,55 +2269,51 @@ Slice::JavaGenerator::findMetadata(const string& prefix, const StringList& metad } bool -Slice::JavaGenerator::getTypeMetadata(const StringList& metadata, string& instanceType, string& formalType) +Slice::JavaGenerator::getTypeMetadata(const MetadataList& metadata, string& instanceType, string& formalType) { // // Extract the instance type and an optional formal type. // The correct syntax is "java:type:instance-type[:formal-type]". // - static const string prefix = "java:type:"; - string directive; - if (findMetadata(prefix, metadata, directive)) + for (const auto& m : metadata) { - string::size_type pos = directive.find(':', prefix.size()); - if (pos != string::npos) - { - instanceType = directive.substr(prefix.size(), pos - prefix.size()); - formalType = directive.substr(pos + 1); - } - else + if (m->directive() == "java:type") { - instanceType = directive.substr(prefix.size()); - formalType.clear(); + string_view arguments = m->arguments(); + string::size_type pos = arguments.find(':'); + if (pos != string::npos) + { + instanceType = string{arguments.substr(0, pos)}; + formalType = string{arguments.substr(pos + 1)}; + } + else + { + instanceType = string{arguments}; + formalType.clear(); + } + return true; } - return true; } return false; } bool -Slice::JavaGenerator::hasTypeMetadata(const TypePtr& type, const StringList& localMetadata) +Slice::JavaGenerator::hasTypeMetadata(const TypePtr& type, const MetadataList& localMetadata) { ContainedPtr cont = dynamic_pointer_cast(type); if (cont) { - static const string prefix = "java:type:"; - string directive; - - if (findMetadata(prefix, localMetadata, directive)) + if (hasMetadata("java:type", localMetadata)) { return true; } - - StringList metadata = cont->getMetadata(); - - if (findMetadata(prefix, metadata, directive)) + if (cont->hasMetadata("java:type")) { return true; } - if (findMetadata("java:serializable:", metadata, directive)) + if (cont->hasMetadata("java:serializable")) { SequencePtr seq = dynamic_pointer_cast(cont); if (seq) @@ -2375,7 +2326,7 @@ Slice::JavaGenerator::hasTypeMetadata(const TypePtr& type, const StringList& loc } } - if (findMetadata("java:buffer", metadata, directive) || findMetadata("java:buffer", localMetadata, directive)) + if (cont->hasMetadata("java:buffer") || hasMetadata("java:buffer", localMetadata)) { SequencePtr seq = dynamic_pointer_cast(cont); if (seq) @@ -2398,15 +2349,15 @@ bool Slice::JavaGenerator::getDictionaryTypes( const DictionaryPtr& dict, const string& package, - const StringList& metadata, + const MetadataList& metadata, string& instanceType, string& formalType) const { // // Get the types of the key and value. // - string keyTypeStr = typeToObjectString(dict->keyType(), TypeModeIn, package, StringList(), true); - string valueTypeStr = typeToObjectString(dict->valueType(), TypeModeIn, package, StringList(), true); + string keyTypeStr = typeToObjectString(dict->keyType(), TypeModeIn, package, MetadataList(), true); + string valueTypeStr = typeToObjectString(dict->valueType(), TypeModeIn, package, MetadataList(), true); // // Collect metadata for a custom type. @@ -2434,7 +2385,7 @@ bool Slice::JavaGenerator::getSequenceTypes( const SequencePtr& seq, const string& package, - const StringList& metadata, + const MetadataList& metadata, string& instanceType, string& formalType) const { @@ -2443,10 +2394,9 @@ Slice::JavaGenerator::getSequenceTypes( { if (builtin->kind() == Builtin::KindByte) { - string prefix = "java:serializable:"; - if (auto meta = seq->findMetadata(prefix)) + if (auto meta = seq->getMetadataArgs("java:serializable")) { - instanceType = formalType = meta->substr(prefix.size()); + instanceType = formalType = *meta; return true; } } @@ -2456,8 +2406,7 @@ Slice::JavaGenerator::getSequenceTypes( builtin->kind() == Builtin::KindFloat || builtin->kind() == Builtin::KindDouble)) { string prefix = "java:buffer"; - string ignored; - if (seq->hasMetadata(prefix) || findMetadata(prefix, metadata, ignored)) + if (seq->hasMetadata(prefix) || hasMetadata(prefix, metadata)) { instanceType = formalType = typeToBufferString(seq->type()); return true; @@ -2475,7 +2424,7 @@ Slice::JavaGenerator::getSequenceTypes( if (formalType.empty()) { formalType = - "java.util.List<" + typeToObjectString(seq->type(), TypeModeIn, package, StringList(), true) + ">"; + "java.util.List<" + typeToObjectString(seq->type(), TypeModeIn, package, MetadataList(), true) + ">"; } return true; } diff --git a/cpp/src/slice2java/JavaUtil.h b/cpp/src/slice2java/JavaUtil.h index 53bc0c29334..ffe17958ea7 100644 --- a/cpp/src/slice2java/JavaUtil.h +++ b/cpp/src/slice2java/JavaUtil.h @@ -142,7 +142,7 @@ namespace Slice const TypePtr&, TypeMode, const std::string& = std::string(), - const StringList& = StringList(), + const MetadataList& = MetadataList(), bool = true, bool = false) const; @@ -155,7 +155,7 @@ namespace Slice const TypePtr&, TypeMode, const std::string& = std::string(), - const StringList& = StringList(), + const MetadataList& = MetadataList(), bool = true) const; // @@ -184,7 +184,7 @@ namespace Slice bool, int&, const std::string& = "", - const StringList& = StringList(), + const MetadataList& = MetadataList(), const std::string& = ""); // @@ -199,7 +199,7 @@ namespace Slice int&, bool, const std::string& = "", - const StringList& = StringList()); + const MetadataList& = MetadataList()); // // Generate code to marshal or unmarshal a sequence type. @@ -213,41 +213,40 @@ namespace Slice int&, bool, const std::string& = "", - const StringList& = StringList()); + const MetadataList& = MetadataList()); // - // Search metadata for an entry with the given prefix and return the entire string. + // Returns true if the metadata has an entry with the given directive, and false otherwise. // - static bool findMetadata(const std::string&, const StringList&, std::string&); + static bool hasMetadata(const std::string&, const MetadataList&); // // Get custom type metadata. If metadata is found, the abstract and // concrete types are extracted and the function returns true. If an // abstract type is not specified, it is set to an empty string. // - static bool getTypeMetadata(const StringList&, std::string&, std::string&); + static bool getTypeMetadata(const MetadataList&, std::string&, std::string&); // // Determine whether a custom type is defined. The function checks the // metadata of the type's original definition, as well as any optional // metadata that typically represents a data member or parameter. // - static bool hasTypeMetadata(const TypePtr&, const StringList& = StringList()); + static bool hasTypeMetadata(const TypePtr&, const MetadataList& = MetadataList()); // // Obtain the concrete and abstract types for a dictionary or sequence type. // The functions return true if a custom type was defined and false to indicate // the default mapping was used. // - bool getDictionaryTypes(const DictionaryPtr&, const std::string&, const StringList&, std::string&, std::string&) + bool + getDictionaryTypes(const DictionaryPtr&, const std::string&, const MetadataList&, std::string&, std::string&) const; bool - getSequenceTypes(const SequencePtr&, const std::string&, const StringList&, std::string&, std::string&) const; + getSequenceTypes(const SequencePtr&, const std::string&, const MetadataList&, std::string&, std::string&) const; JavaOutput* createOutput(); - static const std::string _getSetMetadata; - private: std::string _dir; ::IceInternal::Output* _out; diff --git a/cpp/src/slice2js/Gen.cpp b/cpp/src/slice2js/Gen.cpp index 1a6cfc4b601..da4acd1363c 100644 --- a/cpp/src/slice2js/Gen.cpp +++ b/cpp/src/slice2js/Gen.cpp @@ -943,7 +943,7 @@ Slice::Gen::ImportVisitor::writeImports(const UnitPtr& p) { set sliceTopLevelModules = p->getTopLevelModules(included); - // The JavaScript module corresponding to the "js:module:" metadata in the included file. + // The JavaScript module corresponding to the 'js:module' metadata in the included file. string jsImportedModule = getJavaScriptModule(p->findDefinitionContext(included)); if (jsModule == jsImportedModule || jsImportedModule.empty()) @@ -1989,26 +1989,13 @@ Slice::Gen::TypesVisitor::encodeTypeForOperation(const TypePtr& type) Slice::Gen::TypeScriptImportVisitor::TypeScriptImportVisitor(IceInternal::Output& out) : JsVisitor(out) {} -namespace -{ - string getDefinedIn(const ContainedPtr& p) - { - const string prefix = "js:defined-in:"; - if (auto meta = p->findMetadata(prefix)) - { - return meta->substr(prefix.size()); - } - return ""; - } -} - void Slice::Gen::TypeScriptImportVisitor::addImport(const ContainedPtr& definition) { string jsImportedModule = getJavaScriptModule(definition->definitionContext()); if (jsImportedModule.empty()) { - string definedIn = getDefinedIn(definition); + string definedIn = definition->getMetadataArgs("js:defined-in").value_or(""); if (!definedIn.empty()) { _importedTypes[definition->scoped()] = "__module_" + pathToModule(definedIn) + "."; @@ -2064,7 +2051,7 @@ Slice::Gen::TypeScriptImportVisitor::visitUnitStart(const UnitPtr& unit) // Iterate all the included files and generate an import statement for each top-level module in the included file. for (const auto& included : includes) { - // The JavaScript module corresponding to the "js:module:" metadata in the included file. + // The JavaScript module corresponding to the 'js:module' metadata in the included file. string jsImportedModule = getJavaScriptModule(unit->findDefinitionContext(included)); if (_module != jsImportedModule) diff --git a/cpp/src/slice2js/JsUtil.cpp b/cpp/src/slice2js/JsUtil.cpp index 4b3266f89dd..b1e43f2e3b6 100644 --- a/cpp/src/slice2js/JsUtil.cpp +++ b/cpp/src/slice2js/JsUtil.cpp @@ -142,11 +142,9 @@ Slice::getJavaScriptModuleForType(const TypePtr& type) string Slice::getJavaScriptModule(const DefinitionContextPtr& dc) { - // Check if the file contains the js:module file metadata.- + // Check if the file contains the 'js:module' file metadata. assert(dc); - const string prefix = "js:module:"; - const optional value = dc->findMetadata(prefix); - return value.has_value() ? (*value).substr(prefix.size()) : ""; + return dc->getMetadataArgs("js:module").value_or(""); } // diff --git a/cpp/src/slice2py/PythonUtil.cpp b/cpp/src/slice2py/PythonUtil.cpp index c5d0d267121..75c733ead6c 100644 --- a/cpp/src/slice2py/PythonUtil.cpp +++ b/cpp/src/slice2py/PythonUtil.cpp @@ -150,14 +150,10 @@ namespace Slice void visitConst(const ConstPtr&) final; private: - // - // Validates sequence metadata. - // - StringList validateSequence(const string&, int, const TypePtr&, const StringList&); + /// Validates sequence metadata. + MetadataList validateSequence(const string&, int, const TypePtr&, const MetadataList&); - // - // Checks a definition that doesn't currently support Python metadata. - // + /// Checks a definition that doesn't currently support Python metadata. void reject(const ContainedPtr&); }; @@ -239,7 +235,7 @@ namespace Slice // // Write Python metadata as a tuple. // - void writeMetadata(const StringList&); + void writeMetadata(const MetadataList&); // // Convert an operation mode into a string. @@ -1547,12 +1543,11 @@ void Slice::Python::CodeVisitor::visitSequence(const SequencePtr& p) { // Emit the type information. - StringList metadata = p->getMetadata(); string scoped = p->scoped(); _out << sp << nl << "if " << getDictLookup(p, "_t_") << ':'; _out.inc(); _out << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.defineSequence('" << scoped << "', "; - writeMetadata(metadata); + writeMetadata(p->getMetadata()); _out << ", "; writeType(p->type()); _out << ")"; @@ -1839,19 +1834,19 @@ Slice::Python::CodeVisitor::writeHash(const string& name, const TypePtr& p, int& } void -Slice::Python::CodeVisitor::writeMetadata(const StringList& meta) +Slice::Python::CodeVisitor::writeMetadata(const MetadataList& metadata) { int i = 0; _out << '('; - for (StringList::const_iterator p = meta.begin(); p != meta.end(); ++p) + for (const auto& meta : metadata) { - if (p->find("python:") == 0) + if (meta->directive().find("python:") == 0) { if (i > 0) { _out << ", "; } - _out << "'" << *p << "'"; + _out << "'" << *meta << "'"; ++i; } } @@ -2707,22 +2702,13 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, DocstringMode string Slice::Python::getPackageDirectory(const string& file, const UnitPtr& ut) { - // // file must be a fully-qualified path name. - // - // // Check if the file contains the python:pkgdir file metadata. - // + // If the metadata is present, then the generated file was placed in the specified directory. DefinitionContextPtr dc = ut->findDefinitionContext(file); assert(dc); - const string prefix = "python:pkgdir:"; - if (auto meta = dc->findMetadata(prefix)) - { - // The metadata is present, so the generated file was placed in the specified directory. - return meta->substr(prefix.size()); - } - return ""; + return dc->getMetadataArgs("python:pkgdir").value_or(""); } string @@ -2873,21 +2859,16 @@ Slice::Python::getPackageMetadata(const ContainedPtr& cont) // The python:package metadata can be defined as file metadata or applied to a top-level module. // We check for the metadata at the top-level module first and then fall back to the global scope. - static const string prefix = "python:package:"; - if (auto meta = m->findMetadata(prefix)) + static const string directive = "python:package"; + if (auto packageMetadata = m->getMetadataArgs(directive)) { - return meta->substr(prefix.size()); + return *packageMetadata; } string file = cont->file(); DefinitionContextPtr dc = cont->unit()->findDefinitionContext(file); assert(dc); - if (auto meta = dc->findMetadata(prefix)) - { - return meta->substr(prefix.size()); - } - - return ""; + return dc->getMetadataArgs(directive).value_or(""); } string @@ -2927,32 +2908,33 @@ Slice::Python::printHeader(IceInternal::Output& out) bool Slice::Python::MetadataVisitor::visitUnitStart(const UnitPtr& unit) { - static const string prefix = "python:"; - // Validate file metadata in the top-level file and all included files. for (const auto& file : unit->allFiles()) { DefinitionContextPtr dc = unit->findDefinitionContext(file); assert(dc); - StringList fileMetadata = dc->getMetadata(); - for (StringList::const_iterator r = fileMetadata.begin(); r != fileMetadata.end();) + MetadataList fileMetadata = dc->getMetadata(); + for (MetadataList::const_iterator r = fileMetadata.begin(); r != fileMetadata.end();) { - string s = *r++; - if (s.find(prefix) == 0) + MetadataPtr meta = *r++; + string_view directive = meta->directive(); + string_view arguments = meta->arguments(); + + if (directive.find("python:") == 0) { - static const string packagePrefix = "python:package:"; - if (s.find(packagePrefix) == 0 && s.size() > packagePrefix.size()) + if (directive == "python:package" && !arguments.empty()) { continue; } - static const string pkgdirPrefix = "python:pkgdir:"; - if (s.find(pkgdirPrefix) == 0 && s.size() > pkgdirPrefix.size()) + if (directive == "python:pkgdir" && !arguments.empty()) { continue; } - dc->warning(InvalidMetadata, file, -1, "ignoring invalid file metadata `" + s + "'"); - fileMetadata.remove(s); + ostringstream msg; + msg << "ignoring invalid file metadata '" << *meta << "'"; + dc->warning(InvalidMetadata, file, -1, msg.str()); + fileMetadata.remove(meta); } } dc->setMetadata(fileMetadata); @@ -2963,31 +2945,28 @@ Slice::Python::MetadataVisitor::visitUnitStart(const UnitPtr& unit) bool Slice::Python::MetadataVisitor::visitModuleStart(const ModulePtr& p) { - static const string prefix = "python:package:"; - - StringList metadata = p->getMetadata(); - for (StringList::const_iterator r = metadata.begin(); r != metadata.end();) + MetadataList metadata = p->getMetadata(); + for (MetadataList::const_iterator r = metadata.begin(); r != metadata.end();) { - string s = *r++; - if (s.find(prefix) == 0) + MetadataPtr meta = *r++; + string_view directive = meta->directive(); + + if (directive.find("python:") == 0) { - // // Must be a top-level module. - // - if (dynamic_pointer_cast(p->container())) + if (dynamic_pointer_cast(p->container()) && directive == "python:package") { continue; } - } - if (s.find("python:") == 0) - { - p->definitionContext()->warning(InvalidMetadata, p->file(), -1, "ignoring invalid metadata `" + s + "'"); - metadata.remove(s); + ostringstream msg; + msg << "ignoring invalid file metadata '" << *meta << "'"; + p->definitionContext()->warning(InvalidMetadata, p->file(), -1, msg.str()); + metadata.remove(meta); } } - p->setMetadata(metadata); + p->setMetadata(std::move(metadata)); return true; } @@ -3055,9 +3034,7 @@ Slice::Python::MetadataVisitor::visitDataMember(const DataMemberPtr& p) void Slice::Python::MetadataVisitor::visitSequence(const SequencePtr& p) { - StringList metadata = p->getMetadata(); - metadata = validateSequence(p->file(), p->line(), p, metadata); - p->setMetadata(metadata); + p->setMetadata(validateSequence(p->file(), p->line(), p, p->getMetadata())); } void @@ -3078,49 +3055,48 @@ Slice::Python::MetadataVisitor::visitConst(const ConstPtr& p) reject(p); } -StringList +MetadataList Slice::Python::MetadataVisitor::validateSequence( const string& file, int line, const TypePtr& type, - const StringList& metadata) + const MetadataList& metadata) { const UnitPtr ut = type->unit(); const DefinitionContextPtr dc = ut->findDefinitionContext(file); assert(dc); static const string prefix = "python:"; - StringList newMetadata = metadata; - for (StringList::const_iterator p = newMetadata.begin(); p != newMetadata.end();) + MetadataList newMetadata = metadata; + for (MetadataList::const_iterator p = newMetadata.begin(); p != newMetadata.end();) { - string s = *p++; - if (s.find(prefix) == 0) + MetadataPtr s = *p++; + string_view directive = s->directive(); + string_view arguments = s->arguments(); + + if (directive.find(prefix) == 0) { SequencePtr seq = dynamic_pointer_cast(type); if (seq) { - static const string seqPrefix = "python:seq:"; - if (s.find(seqPrefix) == 0) + if (directive == "python:seq") { - string arg = s.substr(seqPrefix.size()); - if (arg == "tuple" || arg == "list" || arg == "default") + if (arguments == "tuple" || arguments == "list" || arguments == "default") { continue; } } - else if (s.size() > prefix.size()) + else if (directive.size() > prefix.size()) { - string arg = s.substr(prefix.size()); - if (arg == "tuple" || arg == "list" || arg == "default") + string_view subArg = directive.substr(prefix.size()); + if (subArg == "tuple" || subArg == "list" || subArg == "default") { continue; } - else if (arg == "array.array" || arg == "numpy.ndarray" || arg.find("memoryview:") == 0) + else if (subArg == "array.array" || subArg == "numpy.ndarray" || subArg.find("memoryview") == 0) { - // // The memoryview sequence metadata is only valid for integral builtin // types excluding strings. - // BuiltinPtr builtin = dynamic_pointer_cast(seq->type()); if (builtin) { @@ -3145,7 +3121,9 @@ Slice::Python::MetadataVisitor::validateSequence( } } } - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + s + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *s << "'"; + dc->warning(InvalidMetadata, file, line, msg.str()); newMetadata.remove(s); } } @@ -3155,21 +3133,22 @@ Slice::Python::MetadataVisitor::validateSequence( void Slice::Python::MetadataVisitor::reject(const ContainedPtr& cont) { - StringList localMetadata = cont->getMetadata(); - static const string prefix = "python:"; + MetadataList localMetadata = cont->getMetadata(); const UnitPtr ut = cont->unit(); const DefinitionContextPtr dc = ut->findDefinitionContext(cont->file()); assert(dc); - for (StringList::const_iterator p = localMetadata.begin(); p != localMetadata.end();) + for (MetadataList::const_iterator p = localMetadata.begin(); p != localMetadata.end();) { - string s = *p++; - if (s.find(prefix) == 0) + MetadataPtr s = *p++; + if (s->directive().find("python:") == 0) { - dc->warning(InvalidMetadata, cont->file(), cont->line(), "ignoring invalid metadata `" + s + "'"); + ostringstream msg; + msg << "ignoring invalid metadata '" << *s << "'"; + dc->warning(InvalidMetadata, cont->file(), cont->line(), msg.str()); localMetadata.remove(s); } } - cont->setMetadata(localMetadata); + cont->setMetadata(std::move(localMetadata)); } diff --git a/cpp/src/slice2swift/Gen.cpp b/cpp/src/slice2swift/Gen.cpp index 3332e9daaf9..bc4e13aceef 100644 --- a/cpp/src/slice2swift/Gen.cpp +++ b/cpp/src/slice2swift/Gen.cpp @@ -25,13 +25,7 @@ namespace { DefinitionContextPtr dc = p->findDefinitionContext(p->topLevelFile()); assert(dc); - - static const string classResolverPrefix = "swift:class-resolver-prefix:"; - if (auto meta = dc->findMetadata(classResolverPrefix)) - { - return meta->substr(classResolverPrefix.size()); - } - return ""; + return dc->getMetadataArgs("swift:class-resolver-prefix").value_or(""); } } @@ -620,7 +614,7 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p) } else { - out << "[" << typeToString(p->type(), p, p->getMetadata(), false) << "]"; + out << "[" << typeToString(p->type(), p, false) << "]"; } if (builtin && builtin->kind() <= Builtin::KindString) @@ -764,8 +758,8 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) const string swiftModule = getSwiftModule(getTopLevelModule(dynamic_pointer_cast(p))); const string name = getRelativeTypeString(p, swiftModule); - const string keyType = typeToString(p->keyType(), p, p->keyMetadata(), false); - const string valueType = typeToString(p->valueType(), p, p->valueMetadata(), false); + const string keyType = typeToString(p->keyType(), p, false); + const string valueType = typeToString(p->valueType(), p, false); out << sp; writeDocSummary(out, p); out << nl << "public typealias " << fixIdent(name) << " = [" << keyType << ": " << valueType << "]"; @@ -1020,7 +1014,7 @@ Gen::TypesVisitor::visitConst(const ConstPtr& p) writeDocSummary(out, p); out << nl << "public let " << name << ": " << typeToString(type, p) << " = "; - writeConstantValue(out, type, p->valueType(), p->value(), p->getMetadata(), swiftModule); + writeConstantValue(out, type, p->valueType(), p->value(), swiftModule); out << nl; } @@ -1463,16 +1457,12 @@ Gen::ObjectVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) baseNames.push_back(fixIdent(getRelativeTypeString(*i, swiftModule))); } - // - // Check for swift:inherits metadata. - // - const StringList metadata = p->getMetadata(); - static const string prefix = "swift:inherits:"; - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + // Check for 'swift:inherits' metadata. + for (const auto& metadata : p->getMetadata()) { - if (q->find(prefix) == 0) + if (metadata->directive() == "swift:inherits") { - baseNames.push_back(q->substr(prefix.size())); + baseNames.push_back(string{metadata->arguments()}); } } diff --git a/cpp/src/slice2swift/SwiftUtil.cpp b/cpp/src/slice2swift/SwiftUtil.cpp index c7e35f3a167..227174e3b40 100644 --- a/cpp/src/slice2swift/SwiftUtil.cpp +++ b/cpp/src/slice2swift/SwiftUtil.cpp @@ -187,19 +187,19 @@ Slice::fixIdent(const string& ident) string Slice::getSwiftModule(const ModulePtr& module, string& swiftPrefix) { - const string modulePrefix = "swift:module:"; - string swiftModule; - - if (auto meta = module->findMetadata(modulePrefix)) + if (auto argument = module->getMetadataArgs("swift:module")) { - swiftModule = meta->substr(modulePrefix.size()); - - size_t pos = swiftModule.find(':'); + size_t pos = argument->find(':'); if (pos != string::npos) { - swiftPrefix = swiftModule.substr(pos + 1); - swiftModule = swiftModule.substr(0, pos); + swiftModule = argument->substr(0, pos); + swiftPrefix = argument->substr(pos + 1); + } + else + { + swiftModule = *argument; + swiftPrefix = ""; } } else @@ -1023,7 +1023,6 @@ SwiftGenerator::writeConstantValue( const TypePtr& type, const SyntaxTreeBasePtr& valueType, const string& value, - const StringList&, const string& swiftModule, bool optional) { @@ -1068,11 +1067,7 @@ SwiftGenerator::writeConstantValue( } string -SwiftGenerator::typeToString( - const TypePtr& type, - const ContainedPtr& toplevel, - const StringList& metadata, - bool optional) +SwiftGenerator::typeToString(const TypePtr& type, const ContainedPtr& toplevel, bool optional) { static const char* builtinTable[] = { "Swift.UInt8", @@ -1099,7 +1094,6 @@ SwiftGenerator::typeToString( // string currentModule = getSwiftModule(getTopLevelModule(toplevel)); BuiltinPtr builtin = dynamic_pointer_cast(type); - bool nonnull = find(metadata.begin(), metadata.end(), "swift:nonnull") != metadata.end(); if (builtin) { @@ -1130,7 +1124,7 @@ SwiftGenerator::typeToString( t = fixIdent(getRelativeTypeString(cont, currentModule)); } - if (!nonnull && (optional || isNullableType(type))) + if (optional || isNullableType(type)) { t += "?"; } @@ -1325,7 +1319,7 @@ SwiftGenerator::writeMemberwiseInitializer( for (DataMemberList::const_iterator i = allMembers.begin(); i != allMembers.end(); ++i) { DataMemberPtr m = *i; - out << (fixIdent(m->name()) + ": " + typeToString(m->type(), p, m->getMetadata(), m->optional())); + out << (fixIdent(m->name()) + ": " + typeToString(m->type(), p, m->optional())); } out << epar; out << sb; @@ -1367,7 +1361,7 @@ SwiftGenerator::writeMembers( const string defaultValue = member->defaultValue(); const string memberName = fixIdent(member->name()); - string memberType = typeToString(type, p, member->getMetadata(), member->optional()); + string memberType = typeToString(type, p, member->optional()); // // If the member type is equal to the member name, create a local type alias @@ -1399,7 +1393,6 @@ SwiftGenerator::writeMembers( type, member->defaultValueType(), defaultValue, - p->getMetadata(), swiftModule, member->optional()); } @@ -1760,7 +1753,7 @@ SwiftGenerator::operationReturnType(const OperationPtr& op) { os << paramLabel("returnValue", outParams) << ": "; } - os << typeToString(returnType, op, op->getMetadata(), op->returnIsOptional()); + os << typeToString(returnType, op, op->returnIsOptional()); } for (ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q) @@ -1775,7 +1768,7 @@ SwiftGenerator::operationReturnType(const OperationPtr& op) os << (*q)->name() << ": "; } - os << typeToString((*q)->type(), *q, (*q)->getMetadata(), (*q)->optional()); + os << typeToString((*q)->type(), *q, (*q)->optional()); } if (returnIsTuple) @@ -1863,7 +1856,7 @@ SwiftGenerator::operationInParamsDeclaration(const OperationPtr& op) os << ", "; } - os << typeToString((*q)->type(), *q, (*q)->getMetadata(), (*q)->optional()); + os << typeToString((*q)->type(), *q, (*q)->optional()); } if (isTuple) { @@ -1884,7 +1877,7 @@ SwiftGenerator::getAllInParams(const OperationPtr& op) ParamInfo info; info.name = (*p)->name(); info.type = (*p)->type(); - info.typeStr = typeToString(info.type, op, (*p)->getMetadata(), (*p)->optional()); + info.typeStr = typeToString(info.type, op, (*p)->optional()); info.optional = (*p)->optional(); info.tag = (*p)->tag(); info.param = *p; @@ -1931,7 +1924,7 @@ SwiftGenerator::getAllOutParams(const OperationPtr& op) ParamInfo info; info.name = (*p)->name(); info.type = (*p)->type(); - info.typeStr = typeToString(info.type, op, (*p)->getMetadata(), (*p)->optional()); + info.typeStr = typeToString(info.type, op, (*p)->optional()); info.optional = (*p)->optional(); info.tag = (*p)->tag(); info.param = *p; @@ -1943,7 +1936,7 @@ SwiftGenerator::getAllOutParams(const OperationPtr& op) ParamInfo info; info.name = paramLabel("returnValue", params); info.type = op->returnType(); - info.typeStr = typeToString(info.type, op, op->getMetadata(), op->returnIsOptional()); + info.typeStr = typeToString(info.type, op, op->returnIsOptional()); info.optional = op->returnIsOptional(); info.tag = op->returnTag(); l.push_back(info); @@ -2224,14 +2217,13 @@ SwiftGenerator::writeUnmarshalUserException(::IceInternal::Output& out, const Op } void -SwiftGenerator::writeSwiftAttributes(::IceInternal::Output& out, const StringList& metadata) +SwiftGenerator::writeSwiftAttributes(::IceInternal::Output& out, const MetadataList& metadata) { - static const string prefix = "swift:attribute:"; - for (StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q) + for (const auto& meta : metadata) { - if (q->find(prefix) == 0 && q->size() > prefix.size()) + if (meta->directive() == "swift:attribute") { - out << nl << q->substr(prefix.size()); + out << nl << meta->arguments(); } } } @@ -2387,6 +2379,8 @@ SwiftGenerator::MetadataVisitor::visitClassDefStart(const ClassDefPtr& p) p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); for (const auto& member : p->dataMembers()) { + // TODO we should probably be passing `member` instead of `member->type()`. + // Otherwise I'm pretty sure we're just skipping the data-member metadata. member->setMetadata(validate(member->type(), member->getMetadata(), p->file(), member->line())); } return true; @@ -2402,23 +2396,7 @@ SwiftGenerator::MetadataVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p void SwiftGenerator::MetadataVisitor::visitOperation(const OperationPtr& p) { - StringList metadata = p->getMetadata(); - - const UnitPtr ut = p->unit(); - const DefinitionContextPtr dc = ut->findDefinitionContext(p->file()); - assert(dc); - - for (StringList::iterator q = metadata.begin(); q != metadata.end();) - { - string s = *q++; - if (s.find("swift:attribute:") == 0 || s.find("swift:type:") == 0 || s == "swift:noexcept" || - s == "swift:nonnull") - { - dc->warning(InvalidMetadata, p->file(), p->line(), "ignoring metadata `" + s + "' for non local operation"); - metadata.remove(s); - } - } - p->setMetadata(validate(p, metadata, p->file(), p->line())); + p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); for (const auto& param : p->parameters()) { param->setMetadata(validate(param->type(), param->getMetadata(), param->file(), param->line())); @@ -2460,37 +2438,24 @@ SwiftGenerator::MetadataVisitor::visitDictionary(const DictionaryPtr& p) const DefinitionContextPtr dc = p->unit()->findDefinitionContext(p->file()); assert(dc); - StringList newMetadata = p->keyMetadata(); - for (StringList::const_iterator q = newMetadata.begin(); q != newMetadata.end();) + for (const auto& metadata : p->keyMetadata()) { - string s = *q++; - if (s.find(prefix) != 0) + if (metadata->directive().find(prefix) == 0) { - continue; + ostringstream msg; + msg << "ignoring invalid metadata '" << *metadata << "' for dictionary key type"; + dc->warning(InvalidMetadata, p->file(), p->line(), msg.str()); } - - dc->warning( - InvalidMetadata, - p->file(), - p->line(), - "ignoring invalid metadata '" + s + "' for dictionary key type"); } - newMetadata = p->valueMetadata(); - TypePtr t = p->valueType(); - for (StringList::const_iterator q = newMetadata.begin(); q != newMetadata.end();) + for (const auto& metadata : p->valueMetadata()) { - string s = *q++; - if (s.find(prefix) != 0) + if (metadata->directive().find(prefix) == 0) { - continue; + ostringstream msg; + msg << "ignoring invalid metadata '" << *metadata << "' for dictionary value type"; + dc->warning(InvalidMetadata, p->file(), p->line(), msg.str()); } - - dc->warning( - InvalidMetadata, - p->file(), - p->line(), - "ignoring invalid metadata '" + s + "' for dictionary value type"); } p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); @@ -2508,46 +2473,50 @@ SwiftGenerator::MetadataVisitor::visitConst(const ConstPtr& p) p->setMetadata(validate(p, p->getMetadata(), p->file(), p->line())); } -StringList +MetadataList SwiftGenerator::MetadataVisitor::validate( const SyntaxTreeBasePtr& cont, - const StringList& metadata, + const MetadataList& metadata, const string& file, int line) { - StringList newMetadata = metadata; - const string prefix = "swift:"; + MetadataList newMetadata = metadata; const UnitPtr ut = cont->unit(); const DefinitionContextPtr dc = ut->findDefinitionContext(file); assert(dc); - for (StringList::const_iterator p = newMetadata.begin(); p != newMetadata.end();) + + for (MetadataList::const_iterator p = newMetadata.begin(); p != newMetadata.end();) { - string s = *p++; - if (s.find(prefix) != 0) + MetadataPtr meta = *p++; + string_view directive = meta->directive(); + string_view arguments = meta->arguments(); + + if (directive.find("swift:") != 0) { continue; } - if (dynamic_pointer_cast(cont) && s.find("swift:module:") == 0) + if (dynamic_pointer_cast(cont) && directive == "swift:module" && !arguments.empty()) { continue; } - if (dynamic_pointer_cast(cont) && s.find("swift:inherits:") == 0) + if (dynamic_pointer_cast(cont) && directive == "swift:inherits" && !arguments.empty()) { continue; } if ((dynamic_pointer_cast(cont) || dynamic_pointer_cast(cont) || - dynamic_pointer_cast(cont) || dynamic_pointer_cast(cont) || - dynamic_pointer_cast(cont)) && - s.find("swift:attribute:") == 0) + dynamic_pointer_cast(cont) || dynamic_pointer_cast(cont)) && + directive == "swift:attribute" && !arguments.empty()) { continue; } - dc->warning(InvalidMetadata, file, line, "ignoring invalid metadata `" + s + "'"); - newMetadata.remove(s); + ostringstream msg; + msg << "ignoring invalid metadata '" << *meta << "'"; + dc->warning(InvalidMetadata, file, line, msg.str()); + newMetadata.remove(meta); continue; } return newMetadata; diff --git a/cpp/src/slice2swift/SwiftUtil.h b/cpp/src/slice2swift/SwiftUtil.h index a06a575d690..184470ee1ae 100644 --- a/cpp/src/slice2swift/SwiftUtil.h +++ b/cpp/src/slice2swift/SwiftUtil.h @@ -88,7 +88,7 @@ namespace Slice ParamInfoList getAllOutParams(const OperationPtr&); void getOutParams(const OperationPtr&, ParamInfoList&, ParamInfoList&); - std::string typeToString(const TypePtr&, const ContainedPtr&, const StringList& = StringList(), bool = false); + std::string typeToString(const TypePtr&, const ContainedPtr&, bool = false); std::string getUnqualified(const std::string&, const std::string&); std::string modeToString(Operation::Mode); @@ -109,7 +109,6 @@ namespace Slice const TypePtr&, const SyntaxTreeBasePtr&, const std::string&, - const StringList&, const std::string&, bool optional = false); void writeDefaultInitializer(IceInternal::Output&, bool, bool); @@ -138,7 +137,7 @@ namespace Slice void writeUnmarshalInParams(::IceInternal::Output&, const OperationPtr&); void writeUnmarshalOutParams(::IceInternal::Output&, const OperationPtr&); void writeUnmarshalUserException(::IceInternal::Output& out, const OperationPtr&); - void writeSwiftAttributes(::IceInternal::Output&, const StringList&); + void writeSwiftAttributes(::IceInternal::Output&, const MetadataList&); void writeProxyOperation(::IceInternal::Output&, const OperationPtr&); void writeDispatchOperation(::IceInternal::Output&, const OperationPtr&); @@ -160,7 +159,7 @@ namespace Slice bool shouldVisitIncludedDefinitions() const final { return true; } private: - StringList validate(const SyntaxTreeBasePtr&, const StringList&, const std::string&, int); + MetadataList validate(const SyntaxTreeBasePtr&, const MetadataList&, const std::string&, int); typedef std::map ModuleMap; typedef std::map ModulePrefix; diff --git a/cpp/test/Slice/errorDetection/WarningInvalidMetadata.err b/cpp/test/Slice/errorDetection/WarningInvalidMetadata.err index c2e835bead3..efd49bc27d4 100644 --- a/cpp/test/Slice/errorDetection/WarningInvalidMetadata.err +++ b/cpp/test/Slice/errorDetection/WarningInvalidMetadata.err @@ -1,21 +1,21 @@ -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:header-ext:hh': directive can appear only once per file -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:source-ext:cc': directive can appear only once per file -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:dll-export:Test': directive can appear only once per file -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:header-ext' -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:header-ext:' -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:source-ext' -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:source-ext:' -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:dll-export' -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:dll-export:' -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:include' -WarningInvalidMetadata.ice: warning: ignoring invalid file metadata `cpp:include:' -WarningInvalidMetadata.ice:35: warning: ignoring invalid metadata `cpp:type:std::list<::std::string>' for operation with void return type -WarningInvalidMetadata.ice:38: warning: ignoring invalid metadata `cpp:array' for operation with void return type -WarningInvalidMetadata.ice:40: warning: ignoring invalid metadata `cpp:type:my_string' -WarningInvalidMetadata.ice:42: warning: ignoring invalid metadata `cpp:view-type:my_string' -WarningInvalidMetadata.ice:47: warning: ignoring invalid metadata `cpp:const' -WarningInvalidMetadata.ice:47: warning: ignoring invalid metadata `cpp:ice_print' -WarningInvalidMetadata.ice:53: warning: ignoring invalid metadata `cpp:virtual' -WarningInvalidMetadata.ice:58: warning: ignoring invalid metadata `cpp:bad' -WarningInvalidMetadata.ice:63: warning: ignoring invalid metadata `cpp98:foo' -WarningInvalidMetadata.ice:63: warning: ignoring invalid metadata `cpp11:bar' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:header-ext:hh': directive can appear only once per file +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:source-ext:cc': directive can appear only once per file +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:dll-export:Test': directive can appear only once per file +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:header-ext' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:header-ext' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:source-ext' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:source-ext' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:dll-export' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:dll-export' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:include' +WarningInvalidMetadata.ice: warning: ignoring invalid file metadata 'cpp:include' +WarningInvalidMetadata.ice:35: warning: ignoring invalid metadata 'cpp:type:std::list<::std::string>' for operation with void return type +WarningInvalidMetadata.ice:38: warning: ignoring invalid metadata 'cpp:array' for operation with void return type +WarningInvalidMetadata.ice:40: warning: ignoring invalid metadata 'cpp:type:my_string' +WarningInvalidMetadata.ice:42: warning: ignoring invalid metadata 'cpp:view-type:my_string' +WarningInvalidMetadata.ice:47: warning: ignoring invalid metadata 'cpp:const' +WarningInvalidMetadata.ice:47: warning: ignoring invalid metadata 'cpp:ice_print' +WarningInvalidMetadata.ice:53: warning: ignoring invalid metadata 'cpp:virtual' +WarningInvalidMetadata.ice:58: warning: ignoring invalid metadata 'cpp:bad' +WarningInvalidMetadata.ice:63: warning: ignoring invalid metadata 'cpp98:foo' +WarningInvalidMetadata.ice:63: warning: ignoring invalid metadata 'cpp11:bar'