|
|
@@ -52,102 +52,6 @@ TEST_F(ParseTreeTest, IsValid) {
|
|
|
EXPECT_TRUE((*tree.postorder().begin()).is_valid());
|
|
|
}
|
|
|
|
|
|
-TEST_F(ParseTreeTest, OperatorWhitespaceErrors) {
|
|
|
- // Test dispositions: Recovered means we issued an error but recovered a
|
|
|
- // proper parse tree; Failed means we didn't fully recover from the error.
|
|
|
- enum Kind { Valid, Recovered, Failed };
|
|
|
-
|
|
|
- struct Testcase {
|
|
|
- const char* input;
|
|
|
- Kind kind;
|
|
|
- } testcases[] = {
|
|
|
- {"var v: Type = i8*;", Valid},
|
|
|
- {"var v: Type = i8 *;", Recovered},
|
|
|
- {"var v: Type = i8* ;", Valid},
|
|
|
- {"var v: Type = i8 * ;", Recovered},
|
|
|
- {"var n: i8 = n * n;", Valid},
|
|
|
- {"var n: i8 = n*n;", Valid},
|
|
|
- {"var n: i8 = (n)*3;", Valid},
|
|
|
- {"var n: i8 = 3*(n);", Valid},
|
|
|
- {"var n: i8 = n *n;", Recovered},
|
|
|
- // TODO: We could figure out that this first Failed example is infix
|
|
|
- // with one-token lookahead.
|
|
|
- {"var n: i8 = n* n;", Failed},
|
|
|
- {"var n: i8 = n* -n;", Failed},
|
|
|
- {"var n: i8 = n* *p;", Failed},
|
|
|
- // TODO: We try to form (n*)*p and reject due to missing parentheses
|
|
|
- // before we notice the missing whitespace around the second `*`.
|
|
|
- // It'd be better to (somehow) form n*(*p) and reject due to the missing
|
|
|
- // whitespace around the first `*`.
|
|
|
- {"var n: i8 = n**p;", Failed},
|
|
|
- {"var n: i8 = -n;", Valid},
|
|
|
- {"var n: i8 = - n;", Recovered},
|
|
|
- {"var n: i8 =-n;", Valid},
|
|
|
- {"var n: i8 =- n;", Recovered},
|
|
|
- {"var n: i8 = F(i8 *);", Recovered},
|
|
|
- {"var n: i8 = F(i8 *, 0);", Recovered},
|
|
|
- };
|
|
|
-
|
|
|
- for (auto [input, kind] : testcases) {
|
|
|
- TokenizedBuffer tokens = GetTokenizedBuffer(input);
|
|
|
- ErrorTrackingDiagnosticConsumer error_tracker(consumer);
|
|
|
- ParseTree tree =
|
|
|
- ParseTree::Parse(tokens, error_tracker, /*vlog_stream=*/nullptr);
|
|
|
- EXPECT_THAT(tree.has_errors(), Eq(kind == Failed)) << input;
|
|
|
- EXPECT_THAT(error_tracker.seen_error(), Eq(kind != Valid)) << input;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-TEST_F(ParseTreeTest, StructErrors) {
|
|
|
- struct Testcase {
|
|
|
- llvm::StringLiteral input;
|
|
|
- ::testing::Matcher<const Diagnostic&> diag_matcher;
|
|
|
- };
|
|
|
- Testcase testcases[] = {
|
|
|
- {"var x: {i32} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type` or `.field = value`.")},
|
|
|
- {"var x: {a} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type` or `.field = value`.")},
|
|
|
- {"var x: {a:} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type` or `.field = value`.")},
|
|
|
- {"var x: {a=} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type` or `.field = value`.")},
|
|
|
- {"var x: {.} = {};",
|
|
|
- IsDiagnosticMessage("Expected identifier after `.`.")},
|
|
|
- {"var x: {.\"hello\" = 0, .y = 4} = {};",
|
|
|
- IsDiagnosticMessage("Expected identifier after `.`.")},
|
|
|
- {"var x: {.\"hello\": i32, .y: i32} = {};",
|
|
|
- IsDiagnosticMessage("Expected identifier after `.`.")},
|
|
|
- {"var x: {.a} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type` or `.field = value`.")},
|
|
|
- {"var x: {.a:} = {};", IsDiagnosticMessage("Expected expression.")},
|
|
|
- {"var x: {.a=} = {};", IsDiagnosticMessage("Expected expression.")},
|
|
|
- {"var x: {.a: i32, .b = 0} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type`.")},
|
|
|
- {"var x: {.a = 0, b: i32} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field = value`.")},
|
|
|
- {"var x: {,} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type` or `.field = value`.")},
|
|
|
- {"var x: {.a: i32,,} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field: type`.")},
|
|
|
- {"var x: {.a = 0,,} = {};",
|
|
|
- IsDiagnosticMessage("Expected `.field = value`.")},
|
|
|
- {"var x: {.a: i32 banana} = {.a = 0};",
|
|
|
- IsDiagnosticMessage("Expected `,` or `}`.")},
|
|
|
- {"var x: {.a: i32} = {.a = 0 banana};",
|
|
|
- IsDiagnosticMessage("Expected `,` or `}`.")},
|
|
|
- };
|
|
|
-
|
|
|
- for (const Testcase& testcase : testcases) {
|
|
|
- TokenizedBuffer tokens = GetTokenizedBuffer(testcase.input);
|
|
|
- Testing::MockDiagnosticConsumer consumer;
|
|
|
- EXPECT_CALL(consumer, HandleDiagnostic(testcase.diag_matcher));
|
|
|
- ParseTree tree =
|
|
|
- ParseTree::Parse(tokens, consumer, /*vlog_stream=*/nullptr);
|
|
|
- EXPECT_TRUE(tree.has_errors());
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
TEST_F(ParseTreeTest, PrintPostorderAsYAML) {
|
|
|
TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
|
|
|
ParseTree tree = ParseTree::Parse(tokens, consumer, /*vlog_stream=*/nullptr);
|
|
|
@@ -223,38 +127,5 @@ TEST_F(ParseTreeTest, HighRecursion) {
|
|
|
EXPECT_FALSE(tree.has_errors());
|
|
|
}
|
|
|
|
|
|
-TEST_F(ParseTreeTest, PackageErrors) {
|
|
|
- struct TestCase {
|
|
|
- llvm::StringLiteral input;
|
|
|
- ::testing::Matcher<const Diagnostic&> diag_matcher;
|
|
|
- };
|
|
|
-
|
|
|
- TestCase testcases[] = {
|
|
|
- {"package;", IsDiagnosticMessage("Expected identifier after `package`.")},
|
|
|
- {"package fn;",
|
|
|
- IsDiagnosticMessage("Expected identifier after `package`.")},
|
|
|
- {"package library \"Shapes\" api;",
|
|
|
- IsDiagnosticMessage("Expected identifier after `package`.")},
|
|
|
- {"package Geometry library Shapes api;",
|
|
|
- IsDiagnosticMessage(
|
|
|
- "Expected a string literal to specify the library name.")},
|
|
|
- {"package Geometry \"Shapes\" api;",
|
|
|
- IsDiagnosticMessage("Missing `library` keyword.")},
|
|
|
- {"package Geometry api",
|
|
|
- IsDiagnosticMessage("Expected `;` to end package directive.")},
|
|
|
- {"package Geometry;", IsDiagnosticMessage("Expected a `api` or `impl`.")},
|
|
|
- {R"(package Foo library "bar" "baz";)",
|
|
|
- IsDiagnosticMessage("Expected a `api` or `impl`.")}};
|
|
|
-
|
|
|
- for (const TestCase& testcase : testcases) {
|
|
|
- TokenizedBuffer tokens = GetTokenizedBuffer(testcase.input);
|
|
|
- Testing::MockDiagnosticConsumer consumer;
|
|
|
- EXPECT_CALL(consumer, HandleDiagnostic(testcase.diag_matcher));
|
|
|
- ParseTree tree =
|
|
|
- ParseTree::Parse(tokens, consumer, /*vlog_stream=*/nullptr);
|
|
|
- EXPECT_TRUE(tree.has_errors());
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
} // namespace
|
|
|
} // namespace Carbon::Testing
|