jvikstrom updated this revision to Diff 206393. jvikstrom marked 4 inline comments as done. jvikstrom added a comment.
Changed tests Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63559/new/ https://reviews.llvm.org/D63559 Files: clang-tools-extra/clangd/CMakeLists.txt clang-tools-extra/clangd/SemanticHighlight.cpp clang-tools-extra/clangd/SemanticHighlight.h clang-tools-extra/clangd/unittests/CMakeLists.txt clang-tools-extra/clangd/unittests/SemanticHighlightTests.cpp
Index: clang-tools-extra/clangd/unittests/SemanticHighlightTests.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clangd/unittests/SemanticHighlightTests.cpp @@ -0,0 +1,73 @@ +//===- SemanticHighlightTest.cpp - SemanticHighlightTest 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 "ClangdUnit.h" +#include "Protocol.h" +#include "SemanticHighlight.h" +#include "SourceCode.h" +#include "TestTU.h" +#include "llvm/Support/ScopedPrinter.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +std::vector<SemanticToken> makeSemanticTokens(std::vector<Range> Ranges, + SemanticHighlightKind Kind) { + std::vector<SemanticToken> 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 checkHighlights(std::string Code) { + + Annotations Test(Code); + auto AST = TestTU::withCode(Test.code()).build(); + std::map<SemanticHighlightKind, std::string> KindToString{ + {SemanticHighlightKind::Variable, "Variable"}, + {SemanticHighlightKind::Function, "Function"}}; + std::vector<SemanticToken> ExpectedTokens; + for (auto KindString : KindToString) { + std::vector<SemanticToken> Toks = + makeSemanticTokens(Test.ranges(KindString.second), KindString.first); + ExpectedTokens.insert(ExpectedTokens.end(), Toks.begin(), Toks.end()); + } + + auto ActualTokens = getSemanticHighlights(AST); + EXPECT_THAT(ActualTokens, testing::UnorderedElementsAreArray(ExpectedTokens)); +} + +TEST(SemanticTokenCollector, GetBeginningOfIdentifier) { + checkHighlights(R"cpp( + struct A { + double SomeMember; + }; + void $Function[[foo]](int $Variable[[a]]) { + auto $Variable[[VeryLongVariableName]] = 12312; + A $Variable[[aa]]; + } + )cpp"); +} + +TEST(SemanticTokenCollector, DoesNotGetUnnamedParamDecls) { + checkHighlights(R"cpp( + void $Function[[foo]](int); + )cpp"); +} + +} // namespace +} // namespace clangd +} // namespace clang Index: clang-tools-extra/clangd/unittests/CMakeLists.txt =================================================================== --- clang-tools-extra/clangd/unittests/CMakeLists.txt +++ clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -53,6 +53,7 @@ RenameTests.cpp RIFFTests.cpp SelectionTests.cpp + SemanticHighlightTests.cpp SerializationTests.cpp SourceCodeTests.cpp SymbolCollectorTests.cpp Index: clang-tools-extra/clangd/SemanticHighlight.h =================================================================== --- /dev/null +++ clang-tools-extra/clangd/SemanticHighlight.h @@ -0,0 +1,38 @@ +//==-- SemanticHighlight.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" +#include "Protocol.h" +#include "clang/AST/RecursiveASTVisitor.h" + +namespace clang { +namespace clangd { + +enum class SemanticHighlightKind : int { + Variable = 0, + Function = 1, +}; + +// Contains all information needed for the highlighting a token. +struct SemanticToken { + SemanticHighlightKind Kind; + Range R; +}; + +bool operator==(const SemanticToken &Lhs, const SemanticToken &Rhs); +bool operator!=(const SemanticToken &Lhs, const SemanticToken &Rhs); + +std::vector<SemanticToken> getSemanticHighlights(ParsedAST &AST); + +} // namespace clangd +} // namespace clang + +#endif \ No newline at end of file Index: clang-tools-extra/clangd/SemanticHighlight.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clangd/SemanticHighlight.cpp @@ -0,0 +1,83 @@ +//===--- SemanticHighlight.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 "SemanticHighlight.h" +#include "SourceCode.h" +#include "clang/Lex/Lexer.h" + +namespace clang { +namespace clangd { +namespace { + +// Collects all semantic tokens in an ASTContext. +class SemanticTokenCollector + : private RecursiveASTVisitor<SemanticTokenCollector> { + friend class RecursiveASTVisitor<SemanticTokenCollector>; + std::vector<SemanticToken> Tokens; + ASTContext &Ctx; + const SourceManager &SM; + +public: + SemanticTokenCollector(ParsedAST &AST) + : Ctx(AST.getASTContext()), SM(AST.getSourceManager()) { + Ctx.setTraversalScope(AST.getLocalTopLevelDecls()); + } + std::vector<SemanticToken> collectTokens() { + TraverseAST(Ctx); + return Tokens; + } + +private: + bool VisitVarDecl(VarDecl *Var) { + addSymbol(Var, SemanticHighlightKind::Variable); + return true; + } + bool VisitFunctionDecl(FunctionDecl *Func) { + addSymbol(Func, SemanticHighlightKind::Function); + return true; + } + + void addSymbol(NamedDecl *D, SemanticHighlightKind Kind) { + if (D->getLocation().isMacroID()) { + // FIXME; This is inside a macro. For now skip the token + return; + } + + if (D->getName().size() == 0) { + // Don't add symbols that don't have any length. + return; + } + + auto R = getTokenRange(SM, Ctx.getLangOpts(), D->getLocation()); + if (!R.hasValue()) { + // R should always have a value, if it doesn't something is very wrong. + llvm_unreachable("Tried to add semantic token with an invalid range"); + } + + SemanticToken S; + S.R = R.getValue(); + S.Kind = Kind; + Tokens.push_back(S); + } +}; + +} // namespace + +bool operator==(const SemanticToken &Lhs, const SemanticToken &Rhs) { + return Lhs.Kind == Rhs.Kind && Lhs.R == Rhs.R; +} +bool operator!=(const SemanticToken &Lhs, const SemanticToken &Rhs) { + return !(Lhs == Rhs); +} + +std::vector<SemanticToken> getSemanticHighlights(ParsedAST &AST) { + return SemanticTokenCollector(AST).collectTokens(); +} + +} // namespace clangd +} // namespace clang Index: clang-tools-extra/clangd/CMakeLists.txt =================================================================== --- clang-tools-extra/clangd/CMakeLists.txt +++ clang-tools-extra/clangd/CMakeLists.txt @@ -62,6 +62,7 @@ Quality.cpp RIFF.cpp Selection.cpp + SemanticHighlight.cpp SourceCode.cpp Threading.cpp Trace.cpp
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits