diff --git a/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp b/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp @@ -0,0 +1,69 @@ +//===--- AnnotateHighlightings.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 "refactor/Tweak.h" + +namespace clang { +namespace clangd { +namespace { + +llvm::StringRef highlightingKindToString(HighlightingKind Kind) { + switch (Kind) { + case HighlightingKind::Variable: + return "Variable"; + case HighlightingKind::Function: + return "Function"; + } + llvm_unreachable("unhandled HighlightingKind"); +} + +/// Annotate all highlighting tokens in the current file. This is a hidden tweak +/// which is used to debug semantic highlightings. +/// Before: +/// void f() { int abc; } +/// ^^^^^^^^^^^^^^^^^^^^^ +/// After: +/// void /* Function */ f() { int /* Variable */ abc; } +class AnnotateHighlightings : public Tweak { +public: + const char *id() const override final; + + bool prepare(const Selection &Inputs) override { + return Inputs.ASTSelection.root(); + } + Expected apply(const Selection &Inputs) override; + + std::string title() const override { return "Annotate highlighting tokens"; } + Intent intent() const override { return Refactor; } + bool hidden() const override { return true; } +}; +REGISTER_TWEAK(AnnotateHighlightings) + +Expected AnnotateHighlightings::apply(const Selection &Inputs) { + auto HighlightingTokens = getSemanticHighlightings(Inputs.AST); + auto &SM = Inputs.AST.getSourceManager(); + tooling::Replacements Result; + for (const auto &Token : HighlightingTokens) { + assert(Token.R.start.line == Token.R.end.line && + "Token must be at the same line"); + auto InsertOffset = positionToOffset(Inputs.Code, Token.R.start); + if (!InsertOffset) + return InsertOffset.takeError(); + + auto InsertReplacement = tooling::Replacement( + SM.getFileEntryForID(SM.getMainFileID())->getName(), *InsertOffset, 0, + ("/* " + highlightingKindToString(Token.Kind) + " */").str()); + if (auto Err = Result.add(InsertReplacement)) + return std::move(Err); + } + return Effect::applyEdit(Result); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt b/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt --- a/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt +++ b/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt @@ -12,6 +12,7 @@ # $ to a list of sources, see # clangd/tool/CMakeLists.txt for an example. add_clang_library(clangDaemonTweaks OBJECT + AnnotateHighlightings.cpp DumpAST.cpp RawStringLiteral.cpp SwapIfBranches.cpp diff --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp b/clang-tools-extra/clangd/unittests/TweakTests.cpp --- a/clang-tools-extra/clangd/unittests/TweakTests.cpp +++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp @@ -278,6 +278,14 @@ EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 | int x")); } +TEST(TweakTest, AnnotateHighlightings) { + llvm::StringLiteral ID = "AnnotateHighlightings"; + checkAvailable(ID, "^vo^id^ ^f(^) {^}^"); // available everywhere. + const char *Input = "void ^f() {}"; + const char *Output = "void /* Function */f() {}"; + checkTransform(ID, Input, Output); +} + } // namespace } // namespace clangd } // namespace clang