clang-tools  9.0.0
AnnotateHighlightings.cpp
Go to the documentation of this file.
1 //===--- AnnotateHighlightings.cpp -------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "SemanticHighlighting.h"
9 #include "refactor/Tweak.h"
10 
11 namespace clang {
12 namespace clangd {
13 namespace {
14 
15 /// Annotate all highlighting tokens in the current file. This is a hidden tweak
16 /// which is used to debug semantic highlightings.
17 /// Before:
18 /// void f() { int abc; }
19 /// ^^^^^^^^^^^^^^^^^^^^^
20 /// After:
21 /// void /* entity.name.function.cpp */ f() { int /* variable.cpp */ abc; }
22 class AnnotateHighlightings : public Tweak {
23 public:
24  const char *id() const override final;
25 
26  bool prepare(const Selection &Inputs) override {
27  for (auto N = Inputs.ASTSelection.commonAncestor(); N && !InterestedDecl;
28  N = N->Parent)
29  InterestedDecl = N->ASTNode.get<Decl>();
30  return InterestedDecl;
31  }
32  Expected<Effect> apply(const Selection &Inputs) override;
33 
34  std::string title() const override { return "Annotate highlighting tokens"; }
35  Intent intent() const override { return Refactor; }
36  bool hidden() const override { return true; }
37 
38 private:
39  const Decl *InterestedDecl = nullptr;
40 };
41 REGISTER_TWEAK(AnnotateHighlightings)
42 
43 Expected<Tweak::Effect> AnnotateHighlightings::apply(const Selection &Inputs) {
44  // Store the existing scopes.
45  const auto &BackupScopes = Inputs.AST.getASTContext().getTraversalScope();
46  // Narrow the traversal scope to the selected node.
47  Inputs.AST.getASTContext().setTraversalScope(
48  {const_cast<Decl *>(InterestedDecl)});
49  auto HighlightingTokens = getSemanticHighlightings(Inputs.AST);
50  // Restore the traversal scope.
51  Inputs.AST.getASTContext().setTraversalScope(BackupScopes);
52 
53  auto &SM = Inputs.AST.getSourceManager();
54  tooling::Replacements Result;
55  for (const auto &Token : HighlightingTokens) {
56  assert(Token.R.start.line == Token.R.end.line &&
57  "Token must be at the same line");
58  auto InsertOffset = positionToOffset(Inputs.Code, Token.R.start);
59  if (!InsertOffset)
60  return InsertOffset.takeError();
61 
62  auto InsertReplacement = tooling::Replacement(
63  SM.getFileEntryForID(SM.getMainFileID())->getName(), *InsertOffset, 0,
64  ("/* " + toTextMateScope(Token.Kind) + " */").str());
65  if (auto Err = Result.add(InsertReplacement))
66  return std::move(Err);
67  }
68  return Effect::applyEdit(Result);
69 }
70 
71 } // namespace
72 } // namespace clangd
73 } // namespace clang
llvm::StringRef toTextMateScope(HighlightingKind Kind)
Converts a HighlightingKind to a corresponding TextMate scope (https://manual.macromates.com/en/language_grammars).
#define REGISTER_TWEAK(Subclass)
Definition: Tweak.h:113
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
Definition: SourceCode.cpp:141
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: Rename.cpp:36
std::vector< HighlightingToken > getSemanticHighlightings(ParsedAST &AST)