[clang] 5d15212 - [SyntaxTree][Synthesis] Add support for simple Leafs and test based on tree dump
Eduardo Caldas via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 11:27:30 PDT 2020
Author: Eduardo Caldas
Date: 2020-09-11T18:22:00Z
New Revision: 5d152127d48fbcf47a8d059aa68a84c365ae3cb9
URL: https://github.com/llvm/llvm-project/commit/5d152127d48fbcf47a8d059aa68a84c365ae3cb9
DIFF: https://github.com/llvm/llvm-project/commit/5d152127d48fbcf47a8d059aa68a84c365ae3cb9.diff
LOG: [SyntaxTree][Synthesis] Add support for simple Leafs and test based on tree dump
Differential Revision: https://reviews.llvm.org/D87495
Added:
Modified:
clang/include/clang/Tooling/Syntax/BuildTree.h
clang/lib/Tooling/Syntax/Synthesis.cpp
clang/unittests/Tooling/Syntax/SynthesisTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/Syntax/BuildTree.h b/clang/include/clang/Tooling/Syntax/BuildTree.h
index b7ad50c941d1..c2ae4348bc16 100644
--- a/clang/include/clang/Tooling/Syntax/BuildTree.h
+++ b/clang/include/clang/Tooling/Syntax/BuildTree.h
@@ -24,8 +24,17 @@ syntax::TranslationUnit *buildSyntaxTree(Arena &A,
// Create syntax trees from subtrees not backed by the source code.
-clang::syntax::Leaf *createPunctuation(clang::syntax::Arena &A,
- clang::tok::TokenKind K);
+// Synthesis of Leafs
+/// Create `Leaf` from token with `Spelling` and assert it has the desired
+/// `TokenKind`.
+syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K,
+ StringRef Spelling);
+
+/// Infer the token spelling from its `TokenKind`, then create `Leaf` from
+/// this token
+syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K);
+
+// Synthesis of Syntax Nodes
clang::syntax::EmptyStatement *createEmptyStatement(clang::syntax::Arena &A);
} // namespace syntax
diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp
index 701a1e60a4f3..8d51325706fa 100644
--- a/clang/lib/Tooling/Syntax/Synthesis.cpp
+++ b/clang/lib/Tooling/Syntax/Synthesis.cpp
@@ -5,13 +5,14 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/TokenKinds.h"
#include "clang/Tooling/Syntax/BuildTree.h"
using namespace clang;
/// Exposes private syntax tree APIs required to implement node synthesis.
/// Should not be used for anything else.
-class syntax::FactoryImpl {
+class clang::syntax::FactoryImpl {
public:
static void setCanModify(syntax::Node *N) { N->CanModify = true; }
@@ -21,24 +22,32 @@ class syntax::FactoryImpl {
}
};
-clang::syntax::Leaf *syntax::createPunctuation(clang::syntax::Arena &A,
- clang::tok::TokenKind K) {
- auto Tokens = A.lexBuffer(llvm::MemoryBuffer::getMemBuffer(
- clang::tok::getPunctuatorSpelling(K)))
- .second;
+syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K,
+ StringRef Spelling) {
+ auto Tokens = A.lexBuffer(llvm::MemoryBuffer::getMemBuffer(Spelling)).second;
assert(Tokens.size() == 1);
- assert(Tokens.front().kind() == K);
- auto *L = new (A.getAllocator()) clang::syntax::Leaf(Tokens.begin());
- FactoryImpl::setCanModify(L);
- L->assertInvariants();
- return L;
+ assert(Tokens.front().kind() == K &&
+ "spelling is not lexed into the expected kind of token");
+
+ auto *Leaf = new (A.getAllocator()) syntax::Leaf(Tokens.begin());
+ syntax::FactoryImpl::setCanModify(Leaf);
+ Leaf->assertInvariants();
+ return Leaf;
+}
+
+syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) {
+ const auto *Spelling = tok::getPunctuatorSpelling(K);
+ if (!Spelling)
+ Spelling = tok::getKeywordSpelling(K);
+ assert(Spelling &&
+ "Cannot infer the spelling of the token from its token kind.");
+ return createLeaf(A, K, Spelling);
}
-clang::syntax::EmptyStatement *
-syntax::createEmptyStatement(clang::syntax::Arena &A) {
- auto *S = new (A.getAllocator()) clang::syntax::EmptyStatement;
+syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) {
+ auto *S = new (A.getAllocator()) syntax::EmptyStatement;
FactoryImpl::setCanModify(S);
- FactoryImpl::prependChildLowLevel(S, createPunctuation(A, clang::tok::semi),
+ FactoryImpl::prependChildLowLevel(S, createLeaf(A, tok::semi),
NodeRole::Unknown);
S->assertInvariants();
return S;
diff --git a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp
index 884f3797edef..1c1aef8bd8c8 100644
--- a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp
+++ b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp
@@ -12,33 +12,81 @@
#include "TreeTestBase.h"
#include "clang/Tooling/Syntax/BuildTree.h"
+#include "gtest/gtest.h"
using namespace clang;
using namespace clang::syntax;
namespace {
-INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest,
+class SynthesisTest : public SyntaxTreeTest {
+protected:
+ ::testing::AssertionResult treeDumpEqual(syntax::Node *Root, StringRef Dump) {
+ if (!Root)
+ return ::testing::AssertionFailure()
+ << "Root was not built successfully.";
+
+ auto Actual = StringRef(Root->dump(Arena->getSourceManager())).trim().str();
+ auto Expected = Dump.trim().str();
+ // EXPECT_EQ shows the
diff between the two strings if they are
diff erent.
+ EXPECT_EQ(Expected, Actual);
+ if (Actual != Expected) {
+ return ::testing::AssertionFailure();
+ }
+ return ::testing::AssertionSuccess();
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(SynthesisTests, SynthesisTest,
::testing::ValuesIn(allTestClangConfigs()), );
-TEST_P(SyntaxTreeTest, Leaf_Punctuation) {
+TEST_P(SynthesisTest, Leaf_Punctuation) {
+ buildTree("", GetParam());
+
+ auto *Leaf = createLeaf(*Arena, tok::comma);
+
+ EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
+',' Detached synthesized
+ )txt"));
+}
+
+TEST_P(SynthesisTest, Leaf_Keyword) {
+ buildTree("", GetParam());
+
+ auto *Leaf = createLeaf(*Arena, tok::kw_if);
+
+ EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
+'if' Detached synthesized
+ )txt"));
+}
+
+TEST_P(SynthesisTest, Leaf_Identifier) {
buildTree("", GetParam());
- auto *C = syntax::createPunctuation(*Arena, tok::comma);
- ASSERT_NE(C, nullptr);
- EXPECT_EQ(C->getToken()->kind(), tok::comma);
- EXPECT_TRUE(C->canModify());
- EXPECT_FALSE(C->isOriginal());
- EXPECT_TRUE(C->isDetached());
+ auto *Leaf = createLeaf(*Arena, tok::identifier, "a");
+
+ EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
+'a' Detached synthesized
+ )txt"));
+}
+
+TEST_P(SynthesisTest, Leaf_Number) {
+ buildTree("", GetParam());
+
+ auto *Leaf = createLeaf(*Arena, tok::numeric_constant, "1");
+
+ EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
+'1' Detached synthesized
+ )txt"));
}
-TEST_P(SyntaxTreeTest, Statement_Empty) {
+TEST_P(SynthesisTest, Statement_EmptyStatement) {
buildTree("", GetParam());
- auto *S = syntax::createEmptyStatement(*Arena);
- ASSERT_NE(S, nullptr);
- EXPECT_TRUE(S->canModify());
- EXPECT_FALSE(S->isOriginal());
- EXPECT_TRUE(S->isDetached());
+ auto *S = createEmptyStatement(*Arena);
+ EXPECT_TRUE(treeDumpEqual(S, R"txt(
+EmptyStatement Detached synthesized
+`-';' synthesized
+ )txt"));
}
} // namespace
More information about the cfe-commits
mailing list