[LLD] [COFF] Handle undefined weak symbols in LTO (#70430)
[llvm-project.git] / clang-tools-extra / clangd / refactor / tweaks / AnnotateHighlightings.cpp
blob3a320260238b6dead9c12bba8b8d1a72541fdead
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 #include "llvm/ADT/StringRef.h"
11 #include "llvm/Support/ScopedPrinter.h"
13 namespace clang {
14 namespace clangd {
15 namespace {
17 /// Annotate all highlighting tokens in the current file. This is a hidden tweak
18 /// which is used to debug semantic highlightings.
19 /// Before:
20 /// void f() { int abc; }
21 /// ^^^^^^^^^^^^^^^^^^^^^
22 /// After:
23 /// void /* entity.name.function.cpp */ f() { int /* variable.cpp */ abc; }
24 class AnnotateHighlightings : public Tweak {
25 public:
26 const char *id() const final;
28 bool prepare(const Selection &Inputs) override { return true; }
29 Expected<Effect> apply(const Selection &Inputs) override;
31 std::string title() const override { return "Annotate highlighting tokens"; }
32 llvm::StringLiteral kind() const override {
33 return CodeAction::REFACTOR_KIND;
35 bool hidden() const override { return true; }
37 REGISTER_TWEAK(AnnotateHighlightings)
39 Expected<Tweak::Effect> AnnotateHighlightings::apply(const Selection &Inputs) {
40 const Decl *CommonDecl = nullptr;
41 for (auto *N = Inputs.ASTSelection.commonAncestor(); N && !CommonDecl;
42 N = N->Parent)
43 CommonDecl = N->ASTNode.get<Decl>();
45 std::vector<HighlightingToken> HighlightingTokens;
46 if (!CommonDecl) {
47 // Now we hit the TUDecl case where commonAncestor() returns null
48 // intendedly. We only annotate tokens in the main file, so use the default
49 // traversal scope (which is the top level decls of the main file).
50 HighlightingTokens = getSemanticHighlightings(
51 *Inputs.AST, /*IncludeInactiveRegionTokens=*/true);
52 } else {
53 // Store the existing scopes.
54 const auto &BackupScopes = Inputs.AST->getASTContext().getTraversalScope();
55 // Narrow the traversal scope to the selected node.
56 Inputs.AST->getASTContext().setTraversalScope(
57 {const_cast<Decl *>(CommonDecl)});
58 HighlightingTokens = getSemanticHighlightings(
59 *Inputs.AST, /*IncludeInactiveRegionTokens=*/true);
60 // Restore the traversal scope.
61 Inputs.AST->getASTContext().setTraversalScope(BackupScopes);
63 auto &SM = Inputs.AST->getSourceManager();
64 tooling::Replacements Result;
65 llvm::StringRef FilePath = SM.getFilename(Inputs.Cursor);
66 for (const auto &Token : HighlightingTokens) {
67 assert(Token.R.start.line == Token.R.end.line &&
68 "Token must be at the same line");
69 auto InsertOffset = positionToOffset(Inputs.Code, Token.R.start);
70 if (!InsertOffset)
71 return InsertOffset.takeError();
73 std::string Comment = "/* ";
74 Comment.append(llvm::to_string(Token.Kind));
75 for (unsigned I = 0;
76 I <= static_cast<unsigned>(HighlightingModifier::LastModifier); ++I) {
77 if (Token.Modifiers & (1 << I)) {
78 Comment.append(" [");
79 Comment.append(llvm::to_string(static_cast<HighlightingModifier>(I)));
80 Comment.push_back(']');
83 Comment.append(" */");
84 auto InsertReplacement =
85 tooling::Replacement(FilePath, *InsertOffset, 0, Comment);
86 if (auto Err = Result.add(InsertReplacement))
87 return std::move(Err);
89 return Effect::mainFileEdit(SM, std::move(Result));
92 } // namespace
93 } // namespace clangd
94 } // namespace clang