brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · 5432b1e Raw
96 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8#include "SemanticHighlighting.h"9#include "refactor/Tweak.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/Support/ScopedPrinter.h"12 13namespace clang {14namespace clangd {15namespace {16 17/// Annotate all highlighting tokens in the current file. This is a hidden tweak18/// 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; }24class AnnotateHighlightings : public Tweak {25public:26  const char *id() const final;27 28  bool prepare(const Selection &Inputs) override { return true; }29  Expected<Effect> apply(const Selection &Inputs) override;30 31  std::string title() const override { return "Annotate highlighting tokens"; }32  llvm::StringLiteral kind() const override {33    return CodeAction::REFACTOR_KIND;34  }35  bool hidden() const override { return true; }36};37REGISTER_TWEAK(AnnotateHighlightings)38 39Expected<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>();44 45  std::vector<HighlightingToken> HighlightingTokens;46  if (!CommonDecl) {47    // Now we hit the TUDecl case where commonAncestor() returns null48    // intendedly. We only annotate tokens in the main file, so use the default49    // 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 std::vector<Decl *> BackupScopes =55        Inputs.AST->getASTContext().getTraversalScope();56    // Narrow the traversal scope to the selected node.57    Inputs.AST->getASTContext().setTraversalScope(58        {const_cast<Decl *>(CommonDecl)});59    HighlightingTokens = getSemanticHighlightings(60        *Inputs.AST, /*IncludeInactiveRegionTokens=*/true);61    // Restore the traversal scope.62    Inputs.AST->getASTContext().setTraversalScope(BackupScopes);63  }64  auto &SM = Inputs.AST->getSourceManager();65  tooling::Replacements Result;66  llvm::StringRef FilePath = SM.getFilename(Inputs.Cursor);67  for (const auto &Token : HighlightingTokens) {68    assert(Token.R.start.line == Token.R.end.line &&69           "Token must be at the same line");70    auto InsertOffset = positionToOffset(Inputs.Code, Token.R.start);71    if (!InsertOffset)72      return InsertOffset.takeError();73 74    std::string Comment = "/* ";75    Comment.append(llvm::to_string(Token.Kind));76    for (unsigned I = 0;77         I <= static_cast<unsigned>(HighlightingModifier::LastModifier); ++I) {78      if (Token.Modifiers & (1 << I)) {79        Comment.append(" [");80        Comment.append(llvm::to_string(static_cast<HighlightingModifier>(I)));81        Comment.push_back(']');82      }83    }84    Comment.append(" */");85    auto InsertReplacement =86        tooling::Replacement(FilePath, *InsertOffset, 0, Comment);87    if (auto Err = Result.add(InsertReplacement))88      return std::move(Err);89  }90  return Effect::mainFileEdit(SM, std::move(Result));91}92 93} // namespace94} // namespace clangd95} // namespace clang96