llvm/clang-tools-extra/clangd/SemanticHighlighting.cpp

//===--- SemanticHighlighting.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 "Config.h"
#include "FindTarget.h"
#include "HeuristicResolver.h"
#include "ParsedAST.h"
#include "Protocol.h"
#include "SourceCode.h"
#include "support/Logger.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <optional>

namespace clang {
namespace clangd {
namespace {

/// Get the last Position on a given line.
llvm::Expected<Position> endOfLine(llvm::StringRef Code, int Line) {}

/// Some names are not written in the source code and cannot be highlighted,
/// e.g. anonymous classes. This function detects those cases.
bool canHighlightName(DeclarationName Name) {}

bool isUniqueDefinition(const NamedDecl *Decl) {}

std::optional<HighlightingKind> kindForType(const Type *TP,
                                            const HeuristicResolver *Resolver);
std::optional<HighlightingKind> kindForDecl(const NamedDecl *D,
                                            const HeuristicResolver *Resolver) {}
std::optional<HighlightingKind> kindForType(const Type *TP,
                                            const HeuristicResolver *Resolver) {}

// Whether T is const in a loose sense - is a variable with this type readonly?
bool isConst(QualType T) {}

// Whether D is const in a loose sense (should it be highlighted as such?)
// FIXME: This is separate from whether *a particular usage* can mutate D.
//        We may want V in V.size() to be readonly even if V is mutable.
bool isConst(const Decl *D) {}

// "Static" means many things in C++, only some get the "static" modifier.
//
// Meanings that do:
// - Members associated with the class rather than the instance.
//   This is what 'static' most often means across languages.
// - static local variables
//   These are similarly "detached from their context" by the static keyword.
//   In practice, these are rarely used inside classes, reducing confusion.
//
// Meanings that don't:
// - Namespace-scoped variables, which have static storage class.
//   This is implicit, so the keyword "static" isn't so strongly associated.
//   If we want a modifier for these, "global scope" is probably the concept.
// - Namespace-scoped variables/functions explicitly marked "static".
//   There the keyword changes *linkage* , which is a totally different concept.
//   If we want to model this, "file scope" would be a nice modifier.
//
// This is confusing, and maybe we should use another name, but because "static"
// is a standard LSP modifier, having one with that name has advantages.
bool isStatic(const Decl *D) {}

bool isAbstract(const Decl *D) {}

bool isVirtual(const Decl *D) {}

bool isDependent(const Decl *D) {}

/// Returns true if `Decl` is considered to be from a default/system library.
/// This currently checks the systemness of the file by include type, although
/// different heuristics may be used in the future (e.g. sysroot paths).
bool isDefaultLibrary(const Decl *D) {}

bool isDefaultLibrary(const Type *T) {}

// For a macro usage `DUMP(foo)`, we want:
//  - DUMP --> "macro"
//  - foo --> "variable".
SourceLocation getHighlightableSpellingToken(SourceLocation L,
                                             const SourceManager &SM) {}

unsigned evaluateHighlightPriority(const HighlightingToken &Tok) {}

// Sometimes we get multiple tokens at the same location:
//
// - findExplicitReferences() returns a heuristic result for a dependent name
//   (e.g. Method) and CollectExtraHighlighting returning a fallback dependent
//   highlighting (e.g. Unknown+Dependent).
// - macro arguments are expanded multiple times and have different roles
// - broken code recovery produces several AST nodes at the same location
//
// We should either resolve these to a single token, or drop them all.
// Our heuristics are:
//
// - token kinds that come with "dependent-name" modifiers are less reliable
//   (these tend to be vague, like Type or Unknown)
// - if we have multiple equally reliable kinds, drop token rather than guess
// - take the union of modifiers from all tokens
//
// In particular, heuristically resolved dependent names get their heuristic
// kind, plus the dependent modifier.
std::optional<HighlightingToken> resolveConflict(const HighlightingToken &A,
                                                 const HighlightingToken &B) {}
std::optional<HighlightingToken>
resolveConflict(ArrayRef<HighlightingToken> Tokens) {}

/// Filter to remove particular kinds of highlighting tokens and modifiers from
/// the output.
class HighlightingFilter {};

/// Consumes source locations and maps them to text ranges for highlightings.
class HighlightingsBuilder {};

std::optional<HighlightingModifier> scopeModifier(const NamedDecl *D) {}

std::optional<HighlightingModifier> scopeModifier(const Type *T) {}

/// Produces highlightings, which are not captured by findExplicitReferences,
/// e.g. highlights dependent names and 'auto' as the underlying type.
class CollectExtraHighlightings
    : public RecursiveASTVisitor<CollectExtraHighlightings> {};
} // namespace

std::vector<HighlightingToken>
getSemanticHighlightings(ParsedAST &AST, bool IncludeInactiveRegionTokens) {}

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {}
std::optional<HighlightingKind>
highlightingKindFromString(llvm::StringRef Name) {}
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K) {}
std::optional<HighlightingModifier>
highlightingModifierFromString(llvm::StringRef Name) {}

bool operator==(const HighlightingToken &L, const HighlightingToken &R) {}
bool operator<(const HighlightingToken &L, const HighlightingToken &R) {}

std::vector<SemanticToken>
toSemanticTokens(llvm::ArrayRef<HighlightingToken> Tokens,
                 llvm::StringRef Code) {}
llvm::StringRef toSemanticTokenType(HighlightingKind Kind) {}

llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier) {}

std::vector<SemanticTokensEdit>
diffTokens(llvm::ArrayRef<SemanticToken> Old,
           llvm::ArrayRef<SemanticToken> New) {}

std::vector<Range> getInactiveRegions(ParsedAST &AST) {}

} // namespace clangd
} // namespace clang