Author: jvikstrom Date: Wed Jun 26 06:08:36 2019 New Revision: 364421 URL: http://llvm.org/viewvc/llvm-project?rev=364421&view=rev Log: [clangd] Added functionality for getting semantic highlights for variable and function declarations
Added: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp clang-tools-extra/trunk/clangd/SemanticHighlighting.h clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=364421&r1=364420&r2=364421&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clangd/CMakeLists.txt Wed Jun 26 06:08:36 2019 @@ -63,6 +63,7 @@ add_clang_library(clangDaemon Quality.cpp RIFF.cpp Selection.cpp + SemanticHighlighting.cpp SourceCode.cpp QueryDriverDatabase.cpp Threading.cpp Added: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp?rev=364421&view=auto ============================================================================== --- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp (added) +++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp Wed Jun 26 06:08:36 2019 @@ -0,0 +1,78 @@ +//===--- SemanticHighlighting.cpp - -------------------------- ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SemanticHighlighting.h" +#include "Logger.h" +#include "SourceCode.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecursiveASTVisitor.h" + +namespace clang { +namespace clangd { +namespace { + +// Collects all semantic tokens in an ASTContext. +class HighlightingTokenCollector + : public RecursiveASTVisitor<HighlightingTokenCollector> { + std::vector<HighlightingToken> Tokens; + ASTContext &Ctx; + const SourceManager &SM; + +public: + HighlightingTokenCollector(ParsedAST &AST) + : Ctx(AST.getASTContext()), SM(AST.getSourceManager()) {} + + std::vector<HighlightingToken> collectTokens() { + Tokens.clear(); + TraverseAST(Ctx); + return Tokens; + } + + bool VisitVarDecl(VarDecl *Var) { + addToken(Var, HighlightingKind::Variable); + return true; + } + bool VisitFunctionDecl(FunctionDecl *Func) { + addToken(Func, HighlightingKind::Function); + return true; + } + +private: + void addToken(const NamedDecl *D, HighlightingKind Kind) { + if (D->getLocation().isMacroID()) + // FIXME: skip tokens inside macros for now. + return; + + if (D->getDeclName().isEmpty()) + // Don't add symbols that don't have any length. + return; + + auto R = getTokenRange(SM, Ctx.getLangOpts(), D->getLocation()); + if (!R) { + // R should always have a value, if it doesn't something is very wrong. + elog("Tried to add semantic token with an invalid range"); + return; + } + + Tokens.push_back({Kind, R.getValue()}); + } +}; + +} // namespace + +bool operator==(const HighlightingToken &Lhs, const HighlightingToken &Rhs) { + return Lhs.Kind == Rhs.Kind && Lhs.R == Rhs.R; +} + +std::vector<HighlightingToken> getSemanticHighlightings(ParsedAST &AST) { + AST.getASTContext().setTraversalScope(AST.getLocalTopLevelDecls()); + return HighlightingTokenCollector(AST).collectTokens(); +} + +} // namespace clangd +} // namespace clang Added: clang-tools-extra/trunk/clangd/SemanticHighlighting.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/SemanticHighlighting.h?rev=364421&view=auto ============================================================================== --- clang-tools-extra/trunk/clangd/SemanticHighlighting.h (added) +++ clang-tools-extra/trunk/clangd/SemanticHighlighting.h Wed Jun 26 06:08:36 2019 @@ -0,0 +1,37 @@ +//==-- SemanticHighlighting.h - Generating highlights from the AST-- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SEMANTICHIGHLIGHT_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SEMANTICHIGHLIGHT_H + +#include "ClangdUnit.h" + +namespace clang { +namespace clangd { + +enum class HighlightingKind { + Variable, + Function, +}; + +// Contains all information needed for the highlighting a token. +struct HighlightingToken { + HighlightingKind Kind; + Range R; +}; + +bool operator==(const HighlightingToken &Lhs, const HighlightingToken &Rhs); + +// Returns all HighlightingTokens from an AST. Only generates highlights for the +// main AST. +std::vector<HighlightingToken> getSemanticHighlightings(ParsedAST &AST); + +} // namespace clangd +} // namespace clang + +#endif Modified: clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt?rev=364421&r1=364420&r2=364421&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt Wed Jun 26 06:08:36 2019 @@ -53,6 +53,7 @@ add_unittest(ClangdUnitTests ClangdTests RenameTests.cpp RIFFTests.cpp SelectionTests.cpp + SemanticHighlightingTests.cpp SerializationTests.cpp SourceCodeTests.cpp SymbolCollectorTests.cpp Added: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp?rev=364421&view=auto ============================================================================== --- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp (added) +++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp Wed Jun 26 06:08:36 2019 @@ -0,0 +1,69 @@ +//==- SemanticHighlightingTests.cpp - SemanticHighlighting tests-*- C++ -* -==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Annotations.h" +#include "SemanticHighlighting.h" +#include "TestTU.h" +#include "gmock/gmock.h" + +namespace clang { +namespace clangd { +namespace { + +std::vector<HighlightingToken> +makeHighlightingTokens(llvm::ArrayRef<Range> Ranges, HighlightingKind Kind) { + std::vector<HighlightingToken> Tokens(Ranges.size()); + for (int I = 0, End = Ranges.size(); I < End; ++I) { + Tokens[I].R = Ranges[I]; + Tokens[I].Kind = Kind; + } + + return Tokens; +} + +void checkHighlightings(llvm::StringRef Code) { + Annotations Test(Code); + auto AST = TestTU::withCode(Test.code()).build(); + static const std::map<HighlightingKind, std::string> KindToString{ + {HighlightingKind::Variable, "Variable"}, + {HighlightingKind::Function, "Function"}}; + std::vector<HighlightingToken> ExpectedTokens; + for (const auto &KindString : KindToString) { + std::vector<HighlightingToken> Toks = + makeHighlightingTokens(Test.ranges(KindString.second), KindString.first); + ExpectedTokens.insert(ExpectedTokens.end(), Toks.begin(), Toks.end()); + } + + auto ActualTokens = getSemanticHighlightings(AST); + EXPECT_THAT(ActualTokens, testing::UnorderedElementsAreArray(ExpectedTokens)); +} + +TEST(SemanticHighlighting, GetsCorrectTokens) { + const char *TestCases[] = { + R"cpp( + struct A { + double SomeMember; + }; + struct { + } $Variable[[HStruct]]; + void $Function[[foo]](int $Variable[[a]]) { + auto $Variable[[VeryLongVariableName]] = 12312; + A $Variable[[aa]]; + } + )cpp", + R"cpp( + void $Function[[foo]](int); + )cpp"}; + for (const auto &TestCase : TestCases) { + checkHighlightings(TestCase); + } +} + +} // namespace +} // namespace clangd +} // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits