Add location information to diagnostics. (#385)

Add simple mocking and testing of diagnostic emission to ensure this
works.
This commit is contained in:
Richard Smith
2021-03-18 21:05:54 -07:00
committed by GitHub
parent b2455d8dba
commit d1757d9979
26 changed files with 621 additions and 172 deletions
+26 -25
View File
@@ -30,7 +30,7 @@ using ::testing::StrEq;
struct ParseTreeTest : ::testing::Test {
std::forward_list<SourceBuffer> source_storage;
std::forward_list<TokenizedBuffer> token_storage;
DiagnosticEmitter emitter = NullDiagnosticEmitter();
DiagnosticConsumer& consumer = ConsoleDiagnosticConsumer();
auto GetSourceBuffer(llvm::Twine t) -> SourceBuffer& {
source_storage.push_front(SourceBuffer::CreateFromText(t.str()));
@@ -38,21 +38,22 @@ struct ParseTreeTest : ::testing::Test {
}
auto GetTokenizedBuffer(llvm::Twine t) -> TokenizedBuffer& {
token_storage.push_front(TokenizedBuffer::Lex(GetSourceBuffer(t), emitter));
token_storage.push_front(
TokenizedBuffer::Lex(GetSourceBuffer(t), consumer));
return token_storage.front();
}
};
TEST_F(ParseTreeTest, Empty) {
TokenizedBuffer tokens = GetTokenizedBuffer("");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_FALSE(tree.HasErrors());
EXPECT_THAT(tree.Postorder().begin(), Eq(tree.Postorder().end()));
}
TEST_F(ParseTreeTest, EmptyDeclaration) {
TokenizedBuffer tokens = GetTokenizedBuffer(";");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_FALSE(tree.HasErrors());
auto it = tree.Postorder().begin();
auto end = tree.Postorder().end();
@@ -76,7 +77,7 @@ TEST_F(ParseTreeTest, EmptyDeclaration) {
TEST_F(ParseTreeTest, BasicFunctionDeclaration) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_FALSE(tree.HasErrors());
EXPECT_THAT(
tree, MatchParseTreeNodes(
@@ -92,14 +93,14 @@ TEST_F(ParseTreeTest, BasicFunctionDeclaration) {
TEST_F(ParseTreeTest, NoDeclarationIntroducerOrSemi) {
TokenizedBuffer tokens = GetTokenizedBuffer("foo bar baz");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree.Postorder().begin(), Eq(tree.Postorder().end()));
}
TEST_F(ParseTreeTest, NoDeclarationIntroducerWithSemi) {
TokenizedBuffer tokens = GetTokenizedBuffer("foo;");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree,
MatchParseTreeNodes({{.kind = ParseNodeKind::EmptyDeclaration(),
@@ -109,7 +110,7 @@ TEST_F(ParseTreeTest, NoDeclarationIntroducerWithSemi) {
TEST_F(ParseTreeTest, JustFunctionIntroducerAndSemi) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn;");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree, MatchParseTreeNodes(
{{.kind = ParseNodeKind::FunctionDeclaration(),
@@ -119,7 +120,7 @@ TEST_F(ParseTreeTest, JustFunctionIntroducerAndSemi) {
TEST_F(ParseTreeTest, RepeatedFunctionIntroducerAndSemi) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn fn;");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree, MatchParseTreeNodes(
{{.kind = ParseNodeKind::FunctionDeclaration(),
@@ -129,7 +130,7 @@ TEST_F(ParseTreeTest, RepeatedFunctionIntroducerAndSemi) {
TEST_F(ParseTreeTest, FunctionDeclarationWithNoSignatureOrSemi) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn foo");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree,
MatchParseTreeNodes(
@@ -141,7 +142,7 @@ TEST_F(ParseTreeTest, FunctionDeclarationWithNoSignatureOrSemi) {
TEST_F(ParseTreeTest,
FunctionDeclarationWithIdentifierInsteadOfSignatureAndSemi) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn foo bar;");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree, MatchParseTreeNodes(
{{.kind = ParseNodeKind::FunctionDeclaration(),
@@ -152,7 +153,7 @@ TEST_F(ParseTreeTest,
TEST_F(ParseTreeTest, FunctionDeclarationWithSingleIdentifierParameterList) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn foo(bar);");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
// Note: this might become valid depending on the parameter syntax, this test
// shouldn't be taken as a sign it should remain invalid.
EXPECT_TRUE(tree.HasErrors());
@@ -170,7 +171,7 @@ TEST_F(ParseTreeTest, FunctionDeclarationWithSingleIdentifierParameterList) {
TEST_F(ParseTreeTest, FunctionDeclarationWithoutName) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn ();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree, MatchParseTreeNodes(
{{.kind = ParseNodeKind::FunctionDeclaration(),
@@ -182,7 +183,7 @@ TEST_F(ParseTreeTest,
FunctionDeclarationWithoutNameAndManyTokensToSkipInGroupedSymbols) {
TokenizedBuffer tokens = GetTokenizedBuffer(
"fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(tree, MatchParseTreeNodes(
{{.kind = ParseNodeKind::FunctionDeclaration(),
@@ -194,7 +195,7 @@ TEST_F(ParseTreeTest, FunctionDeclarationSkipToNewlineWithoutSemi) {
TokenizedBuffer tokens = GetTokenizedBuffer(
"fn ()\n"
"fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(
tree,
@@ -213,7 +214,7 @@ TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineWithSemi) {
" y,\n"
" z);\n"
"fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(
tree,
@@ -234,7 +235,7 @@ TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineWithoutSemi) {
" y,\n"
" z)\n"
"fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(
tree,
@@ -253,7 +254,7 @@ TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineUntilOutdent) {
" y,\n"
" z)\n"
"fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
EXPECT_THAT(
tree,
@@ -275,7 +276,7 @@ TEST_F(ParseTreeTest, FunctionDeclarationSkipWithoutSemiToCurly) {
TokenizedBuffer tokens = GetTokenizedBuffer(
"struct X { fn () }\n"
"fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
}
@@ -283,7 +284,7 @@ TEST_F(ParseTreeTest, BasicFunctionDefinition) {
TokenizedBuffer tokens = GetTokenizedBuffer(
"fn F() {\n"
"}");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_FALSE(tree.HasErrors());
EXPECT_THAT(
tree, MatchParseTreeNodes(
@@ -304,7 +305,7 @@ TEST_F(ParseTreeTest, FunctionDefinitionWithNestedBlocks) {
" {{}}\n"
" }\n"
"}");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_FALSE(tree.HasErrors());
EXPECT_THAT(
tree,
@@ -332,7 +333,7 @@ TEST_F(ParseTreeTest, FunctionDefinitionWithIdenifierInStatements) {
"fn F() {\n"
" bar\n"
"}");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
// Note: this might become valid depending on the expression syntax. This test
// shouldn't be taken as a sign it should remain invalid.
EXPECT_TRUE(tree.HasErrors());
@@ -353,7 +354,7 @@ TEST_F(ParseTreeTest, FunctionDefinitionWithIdenifierInNestedBlock) {
"fn F() {\n"
" {bar}\n"
"}");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
// Note: this might become valid depending on the expression syntax. This test
// shouldn't be taken as a sign it should remain invalid.
EXPECT_TRUE(tree.HasErrors());
@@ -387,7 +388,7 @@ auto GetAndDropLine(llvm::StringRef& s) -> std::string {
TEST_F(ParseTreeTest, Printing) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_FALSE(tree.HasErrors());
std::string print_storage;
llvm::raw_string_ostream print_stream(print_storage);
@@ -413,7 +414,7 @@ TEST_F(ParseTreeTest, Printing) {
TEST_F(ParseTreeTest, PrintingAsYAML) {
TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
ParseTree tree = ParseTree::Parse(tokens, emitter);
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_FALSE(tree.HasErrors());
std::string print_output;
llvm::raw_string_ostream print_stream(print_output);