[fidlc] Allow type aliases anywhere in file
... after library imports of course.
FIDL-582 #comment
Change-Id: I1a75dcc54c46de170c016e3c898bcd65fd136c75
diff --git a/zircon/system/host/fidl/lib/parser.cpp b/zircon/system/host/fidl/lib/parser.cpp
index 66f8d17..c7eacde 100644
--- a/zircon/system/host/fidl/lib/parser.cpp
+++ b/zircon/system/host/fidl/lib/parser.cpp
@@ -1067,6 +1067,7 @@
std::unique_ptr<raw::File> Parser::ParseFile() {
ASTScope scope(this);
+ bool done_with_library_imports = false;
std::vector<std::unique_ptr<raw::Using>> using_list;
std::vector<std::unique_ptr<raw::BitsDeclaration>> bits_declaration_list;
std::vector<std::unique_ptr<raw::ConstDeclaration>> const_declaration_list;
@@ -1090,27 +1091,9 @@
if (!Ok())
return Fail();
- auto parse_using = [&using_list, this]() {
- switch (Peek().combined()) {
- default:
- return Done;
-
- case CASE_IDENTIFIER(Token::Subkind::kUsing):
- using_list.emplace_back(ParseUsing());
- return More;
- }
- };
-
- while (parse_using() == More) {
- if (!Ok())
- return Fail();
- ConsumeToken(OfKind(Token::Kind::kSemicolon));
- if (!Ok())
- return Fail();
- }
-
auto parse_declaration = [&bits_declaration_list, &const_declaration_list, &enum_declaration_list,
&interface_declaration_list, &struct_declaration_list,
+ &done_with_library_imports, &using_list,
&table_declaration_list, &union_declaration_list, &xunion_declaration_list, this]() {
ASTScope scope(this);
std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
@@ -1122,30 +1105,51 @@
return Done;
case CASE_IDENTIFIER(Token::Subkind::kBits):
+ done_with_library_imports = true;
bits_declaration_list.emplace_back(ParseBitsDeclaration(std::move(attributes), scope));
return More;
case CASE_IDENTIFIER(Token::Subkind::kConst):
+ done_with_library_imports = true;
const_declaration_list.emplace_back(ParseConstDeclaration(std::move(attributes), scope));
return More;
case CASE_IDENTIFIER(Token::Subkind::kEnum):
+ done_with_library_imports = true;
enum_declaration_list.emplace_back(ParseEnumDeclaration(std::move(attributes), scope));
return More;
case CASE_IDENTIFIER(Token::Subkind::kProtocol):
+ done_with_library_imports = true;
interface_declaration_list.emplace_back(
ParseProtocolDeclaration(std::move(attributes), scope));
return More;
case CASE_IDENTIFIER(Token::Subkind::kStruct):
+ done_with_library_imports = true;
struct_declaration_list.emplace_back(ParseStructDeclaration(std::move(attributes), scope));
return More;
case CASE_IDENTIFIER(Token::Subkind::kTable):
+ done_with_library_imports = true;
table_declaration_list.emplace_back(ParseTableDeclaration(std::move(attributes), scope));
return More;
+ case CASE_IDENTIFIER(Token::Subkind::kUsing): {
+ auto using_decl = ParseUsing();
+ if (using_decl->maybe_type_ctor) {
+ done_with_library_imports = true;
+ } else if (done_with_library_imports) {
+ // TODO(FIDL-582): Give one week warning, then turn this into
+ // an error.
+ error_reporter_->ReportWarning(
+ using_decl->location(),
+ "library imports must be grouped at top-of-file");
+ }
+ using_list.emplace_back(std::move(using_decl));
+ return More;
+ }
+
case CASE_IDENTIFIER(Token::Subkind::kUnion):
union_declaration_list.emplace_back(ParseUnionDeclaration(std::move(attributes), scope));
return More;
diff --git a/zircon/system/utest/fidl-compiler/parsing_tests.cpp b/zircon/system/utest/fidl-compiler/parsing_tests.cpp
index 7863b98..308b58f 100644
--- a/zircon/system/utest/fidl-compiler/parsing_tests.cpp
+++ b/zircon/system/utest/fidl-compiler/parsing_tests.cpp
@@ -289,6 +289,31 @@
END_TEST;
}
+bool warn_on_type_alias_before_imports() {
+ BEGIN_TEST;
+
+ SharedAmongstLibraries shared;
+ TestLibrary dependency("dependent.fidl", R"FIDL(
+library dependent;
+)FIDL", &shared);
+ ASSERT_TRUE(dependency.Compile());
+
+ TestLibrary library(R"FIDL(
+library example;
+
+using foo = int16;
+using dependent;
+)FIDL");
+ ASSERT_TRUE(library.AddDependentLibrary(std::move(dependency)));
+ ASSERT_TRUE(library.Compile());
+
+ const auto& warnings = library.warnings();
+ ASSERT_EQ(warnings.size(), 1);
+ ASSERT_STR_STR(warnings[0].data(), "library imports must be grouped at top-of-file");
+
+ END_TEST;
+}
+
} // namespace
BEGIN_TEST_CASE(parsing_tests)
@@ -301,4 +326,5 @@
RUN_TEST(bad_identifier_test)
RUN_TEST(invalid_character_test)
RUN_TEST(empty_struct_test)
+RUN_TEST(warn_on_type_alias_before_imports)
END_TEST_CASE(parsing_tests)
diff --git a/zircon/system/utest/fidl-compiler/type_alias_tests.cpp b/zircon/system/utest/fidl-compiler/type_alias_tests.cpp
index 74a1ab9..eb2281b 100644
--- a/zircon/system/utest/fidl-compiler/type_alias_tests.cpp
+++ b/zircon/system/utest/fidl-compiler/type_alias_tests.cpp
@@ -14,6 +14,33 @@
TestLibrary library(R"FIDL(
library example;
+struct Message {
+ alias_of_int16 f;
+};
+
+using alias_of_int16 = int16;
+)FIDL");
+ ASSERT_TRUE(library.Compile());
+ auto msg = library.LookupStruct("Message");
+ ASSERT_NONNULL(msg);
+ ASSERT_EQ(msg->members.size(), 1);
+
+ auto type = msg->members[0].type_ctor->type;
+ ASSERT_EQ(type->kind, fidl::flat::Type::Kind::kPrimitive);
+ ASSERT_EQ(type->nullability, fidl::types::Nullability::kNonnullable);
+
+ auto primitive_type = static_cast<const fidl::flat::PrimitiveType*>(type);
+ ASSERT_EQ(primitive_type->subtype, fidl::types::PrimitiveSubtype::kInt16);
+
+ END_TEST;
+}
+
+bool primitive_type_alias_before_use() {
+ BEGIN_TEST;
+
+ TestLibrary library(R"FIDL(
+library example;
+
using alias_of_int16 = int16;
struct Message {
@@ -41,11 +68,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_of_string = vector<string>;
-
struct Message {
alias_of_vector_of_string f;
};
+
+using alias_of_vector_of_string = vector<string>;
)FIDL");
ASSERT_TRUE(library.Compile());
auto msg = library.LookupStruct("Message");
@@ -70,11 +97,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector = vector;
-
struct Message {
alias_of_vector<uint8> f;
};
+
+using alias_of_vector = vector;
)FIDL");
ASSERT_TRUE(library.Compile());
auto msg = library.LookupStruct("Message");
@@ -102,11 +129,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_max_8 = vector:8;
-
struct Message {
alias_of_vector_max_8<string> f;
};
+
+using alias_of_vector_max_8 = vector:8;
)FIDL");
ASSERT_TRUE(library.Compile());
auto msg = library.LookupStruct("Message");
@@ -131,11 +158,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_of_string = vector<string>;
-
struct Message {
alias_of_vector_of_string:8 f;
};
+
+using alias_of_vector_of_string = vector<string>;
)FIDL");
ASSERT_TRUE(library.Compile());
auto msg = library.LookupStruct("Message");
@@ -160,11 +187,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_of_string_nullable = vector<string>?;
-
struct Message {
alias_of_vector_of_string_nullable f;
};
+
+using alias_of_vector_of_string_nullable = vector<string>?;
)FIDL");
ASSERT_TRUE(library.Compile());
auto msg = library.LookupStruct("Message");
@@ -189,11 +216,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_of_string = vector<string>;
-
struct Message {
alias_of_vector_of_string? f;
};
+
+using alias_of_vector_of_string = vector<string>;
)FIDL");
ASSERT_TRUE(library.Compile());
auto msg = library.LookupStruct("Message");
@@ -218,11 +245,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_of_string = vector<string>;
-
struct Message {
alias_of_vector_of_string<string> f;
};
+
+using alias_of_vector_of_string = vector<string>;
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
@@ -238,11 +265,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_of_string_max_5 = vector<string>:5;
-
struct Message {
alias_of_vector_of_string_max_5:9 f;
};
+
+using alias_of_vector_of_string_max_5 = vector<string>:5;
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
@@ -258,11 +285,11 @@
TestLibrary library(R"FIDL(
library example;
-using alias_of_vector_nullable = vector?;
-
struct Message {
alias_of_vector_nullable<string>? f;
};
+
+using alias_of_vector_nullable = vector?;
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
@@ -276,6 +303,7 @@
BEGIN_TEST_CASE(type_alias_tests)
RUN_TEST(primitive)
+RUN_TEST(primitive_type_alias_before_use)
RUN_TEST(vector_parametrized_on_decl)
RUN_TEST(vector_parametrized_on_use)
RUN_TEST(vector_bounded_on_decl)