clang-tools  14.0.0git
SemanticHighlighting.cpp
Go to the documentation of this file.
1 //===--- SemanticHighlighting.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 
9 #include "SemanticHighlighting.h"
10 #include "FindTarget.h"
11 #include "HeuristicResolver.h"
12 #include "ParsedAST.h"
13 #include "Protocol.h"
14 #include "SourceCode.h"
15 #include "support/Logger.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/DeclObjC.h"
20 #include "clang/AST/DeclTemplate.h"
21 #include "clang/AST/DeclarationName.h"
22 #include "clang/AST/ExprCXX.h"
23 #include "clang/AST/RecursiveASTVisitor.h"
24 #include "clang/AST/Type.h"
25 #include "clang/AST/TypeLoc.h"
26 #include "clang/Basic/LangOptions.h"
27 #include "clang/Basic/SourceLocation.h"
28 #include "clang/Basic/SourceManager.h"
29 #include "clang/Tooling/Syntax/Tokens.h"
30 #include "llvm/ADT/None.h"
31 #include "llvm/ADT/Optional.h"
32 #include "llvm/ADT/STLExtras.h"
33 #include "llvm/Support/Base64.h"
34 #include "llvm/Support/Casting.h"
35 #include <algorithm>
36 
37 namespace clang {
38 namespace clangd {
39 namespace {
40 
41 /// Some names are not written in the source code and cannot be highlighted,
42 /// e.g. anonymous classes. This function detects those cases.
43 bool canHighlightName(DeclarationName Name) {
44  switch (Name.getNameKind()) {
45  case DeclarationName::Identifier: {
46  auto *II = Name.getAsIdentifierInfo();
47  return II && !II->getName().empty();
48  }
49  case DeclarationName::CXXConstructorName:
50  case DeclarationName::CXXDestructorName:
51  return true;
52  case DeclarationName::ObjCZeroArgSelector:
53  case DeclarationName::ObjCOneArgSelector:
54  case DeclarationName::ObjCMultiArgSelector:
55  // Multi-arg selectors need special handling, and we handle 0/1 arg
56  // selectors there too.
57  return false;
58  case DeclarationName::CXXConversionFunctionName:
59  case DeclarationName::CXXOperatorName:
60  case DeclarationName::CXXDeductionGuideName:
61  case DeclarationName::CXXLiteralOperatorName:
62  case DeclarationName::CXXUsingDirective:
63  return false;
64  }
65  llvm_unreachable("invalid name kind");
66 }
67 
68 llvm::Optional<HighlightingKind> kindForType(const Type *TP,
69  const HeuristicResolver *Resolver);
70 llvm::Optional<HighlightingKind>
71 kindForDecl(const NamedDecl *D, const HeuristicResolver *Resolver) {
72  if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {
73  if (auto *Target = USD->getTargetDecl())
74  D = Target;
75  }
76  if (auto *TD = dyn_cast<TemplateDecl>(D)) {
77  if (auto *Templated = TD->getTemplatedDecl())
78  D = Templated;
79  }
80  if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
81  // We try to highlight typedefs as their underlying type.
82  if (auto K =
83  kindForType(TD->getUnderlyingType().getTypePtrOrNull(), Resolver))
84  return K;
85  // And fallback to a generic kind if this fails.
87  }
88  // We highlight class decls, constructor decls and destructor decls as
89  // `Class` type. The destructor decls are handled in `VisitTagTypeLoc` (we
90  // will visit a TypeLoc where the underlying Type is a CXXRecordDecl).
91  if (auto *RD = llvm::dyn_cast<RecordDecl>(D)) {
92  // We don't want to highlight lambdas like classes.
93  if (RD->isLambda())
94  return llvm::None;
96  }
97  if (isa<ClassTemplateDecl, RecordDecl, CXXConstructorDecl, ObjCInterfaceDecl,
98  ObjCImplementationDecl>(D))
100  if (isa<ObjCProtocolDecl>(D))
102  if (isa<ObjCCategoryDecl>(D))
104  if (auto *MD = dyn_cast<CXXMethodDecl>(D))
105  return MD->isStatic() ? HighlightingKind::StaticMethod
107  if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
108  return OMD->isClassMethod() ? HighlightingKind::StaticMethod
110  if (isa<FieldDecl, ObjCPropertyDecl>(D))
112  if (isa<EnumDecl>(D))
113  return HighlightingKind::Enum;
114  if (isa<EnumConstantDecl>(D))
116  if (isa<ParmVarDecl>(D))
118  if (auto *VD = dyn_cast<VarDecl>(D)) {
119  if (isa<ImplicitParamDecl>(VD)) // e.g. ObjC Self
120  return llvm::None;
121  return VD->isStaticDataMember()
123  : VD->isLocalVarDecl() ? HighlightingKind::LocalVariable
125  }
126  if (const auto *BD = dyn_cast<BindingDecl>(D))
127  return BD->getDeclContext()->isFunctionOrMethod()
130  if (isa<FunctionDecl>(D))
132  if (isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D) ||
133  isa<UsingDirectiveDecl>(D))
135  if (isa<TemplateTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
136  isa<NonTypeTemplateParmDecl>(D))
138  if (isa<ConceptDecl>(D))
140  if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(D)) {
141  auto Targets = Resolver->resolveUsingValueDecl(UUVD);
142  if (!Targets.empty()) {
143  return kindForDecl(Targets[0], Resolver);
144  }
146  }
147  return llvm::None;
148 }
149 llvm::Optional<HighlightingKind>
150 kindForType(const Type *TP, const HeuristicResolver *Resolver) {
151  if (!TP)
152  return llvm::None;
153  if (TP->isBuiltinType()) // Builtins are special, they do not have decls.
155  if (auto *TD = dyn_cast<TemplateTypeParmType>(TP))
156  return kindForDecl(TD->getDecl(), Resolver);
157  if (isa<ObjCObjectPointerType>(TP))
159  if (auto *TD = TP->getAsTagDecl())
160  return kindForDecl(TD, Resolver);
161  return llvm::None;
162 }
163 
164 // Whether T is const in a loose sense - is a variable with this type readonly?
165 bool isConst(QualType T) {
166  if (T.isNull() || T->isDependentType())
167  return false;
168  T = T.getNonReferenceType();
169  if (T.isConstQualified())
170  return true;
171  if (const auto *AT = T->getAsArrayTypeUnsafe())
172  return isConst(AT->getElementType());
173  if (isConst(T->getPointeeType()))
174  return true;
175  return false;
176 }
177 
178 // Whether D is const in a loose sense (should it be highlighted as such?)
179 // FIXME: This is separate from whether *a particular usage* can mutate D.
180 // We may want V in V.size() to be readonly even if V is mutable.
181 bool isConst(const Decl *D) {
182  if (llvm::isa<EnumConstantDecl>(D) || llvm::isa<NonTypeTemplateParmDecl>(D))
183  return true;
184  if (llvm::isa<FieldDecl>(D) || llvm::isa<VarDecl>(D) ||
185  llvm::isa<MSPropertyDecl>(D) || llvm::isa<BindingDecl>(D)) {
186  if (isConst(llvm::cast<ValueDecl>(D)->getType()))
187  return true;
188  }
189  if (const auto *OCPD = llvm::dyn_cast<ObjCPropertyDecl>(D)) {
190  if (OCPD->isReadOnly())
191  return true;
192  }
193  if (const auto *MPD = llvm::dyn_cast<MSPropertyDecl>(D)) {
194  if (!MPD->hasSetter())
195  return true;
196  }
197  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
198  if (CMD->isConst())
199  return true;
200  }
201  return false;
202 }
203 
204 // "Static" means many things in C++, only some get the "static" modifier.
205 //
206 // Meanings that do:
207 // - Members associated with the class rather than the instance.
208 // This is what 'static' most often means across languages.
209 // - static local variables
210 // These are similarly "detached from their context" by the static keyword.
211 // In practice, these are rarely used inside classes, reducing confusion.
212 //
213 // Meanings that don't:
214 // - Namespace-scoped variables, which have static storage class.
215 // This is implicit, so the keyword "static" isn't so strongly associated.
216 // If we want a modifier for these, "global scope" is probably the concept.
217 // - Namespace-scoped variables/functions explicitly marked "static".
218 // There the keyword changes *linkage* , which is a totally different concept.
219 // If we want to model this, "file scope" would be a nice modifier.
220 //
221 // This is confusing, and maybe we should use another name, but because "static"
222 // is a standard LSP modifier, having one with that name has advantages.
223 bool isStatic(const Decl *D) {
224  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
225  return CMD->isStatic();
226  if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
227  return VD->isStaticDataMember() || VD->isStaticLocal();
228  if (const auto *OPD = llvm::dyn_cast<ObjCPropertyDecl>(D))
229  return OPD->isClassProperty();
230  if (const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D))
231  return OMD->isClassMethod();
232  return false;
233 }
234 
235 bool isAbstract(const Decl *D) {
236  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
237  return CMD->isPure();
238  if (const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
239  return CRD->hasDefinition() && CRD->isAbstract();
240  return false;
241 }
242 
243 bool isVirtual(const Decl *D) {
244  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
245  return CMD->isVirtual();
246  return false;
247 }
248 
249 bool isDependent(const Decl *D) {
250  if (isa<UnresolvedUsingValueDecl>(D))
251  return true;
252  return false;
253 }
254 
255 /// Returns true if `Decl` is considered to be from a default/system library.
256 /// This currently checks the systemness of the file by include type, although
257 /// different heuristics may be used in the future (e.g. sysroot paths).
258 bool isDefaultLibrary(const Decl *D) {
259  SourceLocation Loc = D->getLocation();
260  if (!Loc.isValid())
261  return false;
262  return D->getASTContext().getSourceManager().isInSystemHeader(Loc);
263 }
264 
265 bool isDefaultLibrary(const Type *T) {
266  if (!T)
267  return false;
268  const Type *Underlying = T->getPointeeOrArrayElementType();
269  if (Underlying->isBuiltinType())
270  return true;
271  if (auto *TD = dyn_cast<TemplateTypeParmType>(Underlying))
272  return isDefaultLibrary(TD->getDecl());
273  if (auto *TD = Underlying->getAsTagDecl())
274  return isDefaultLibrary(TD);
275  return false;
276 }
277 
278 // For a macro usage `DUMP(foo)`, we want:
279 // - DUMP --> "macro"
280 // - foo --> "variable".
281 SourceLocation getHighlightableSpellingToken(SourceLocation L,
282  const SourceManager &SM) {
283  if (L.isFileID())
284  return SM.isWrittenInMainFile(L) ? L : SourceLocation{};
285  // Tokens expanded from the macro body contribute no highlightings.
286  if (!SM.isMacroArgExpansion(L))
287  return {};
288  // Tokens expanded from macro args are potentially highlightable.
289  return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM);
290 }
291 
292 unsigned evaluateHighlightPriority(const HighlightingToken &Tok) {
293  enum HighlightPriority { Dependent = 0, Resolved = 1 };
294  return (Tok.Modifiers & (1 << uint32_t(HighlightingModifier::DependentName)))
295  ? Dependent
296  : Resolved;
297 }
298 
299 // Sometimes we get multiple tokens at the same location:
300 //
301 // - findExplicitReferences() returns a heuristic result for a dependent name
302 // (e.g. Method) and CollectExtraHighlighting returning a fallback dependent
303 // highlighting (e.g. Unknown+Dependent).
304 // - macro arguments are expanded multiple times and have different roles
305 // - broken code recovery produces several AST nodes at the same location
306 //
307 // We should either resolve these to a single token, or drop them all.
308 // Our heuristics are:
309 //
310 // - token kinds that come with "dependent-name" modifiers are less reliable
311 // (these tend to be vague, like Type or Unknown)
312 // - if we have multiple equally reliable kinds, drop token rather than guess
313 // - take the union of modifiers from all tokens
314 //
315 // In particular, heuristically resolved dependent names get their heuristic
316 // kind, plus the dependent modifier.
317 llvm::Optional<HighlightingToken>
318 resolveConflict(ArrayRef<HighlightingToken> Tokens) {
319  if (Tokens.size() == 1)
320  return Tokens[0];
321 
322  if (Tokens.size() != 2)
323  return llvm::None;
324 
325  unsigned Priority1 = evaluateHighlightPriority(Tokens[0]);
326  unsigned Priority2 = evaluateHighlightPriority(Tokens[1]);
327  if (Priority1 == Priority2 && Tokens[0].Kind != Tokens[1].Kind)
328  return llvm::None;
329  auto Result = Priority1 > Priority2 ? Tokens[0] : Tokens[1];
330  Result.Modifiers = Tokens[0].Modifiers | Tokens[1].Modifiers;
331  return Result;
332 }
333 
334 /// Consumes source locations and maps them to text ranges for highlightings.
335 class HighlightingsBuilder {
336 public:
337  HighlightingsBuilder(const ParsedAST &AST)
338  : TB(AST.getTokens()), SourceMgr(AST.getSourceManager()),
339  LangOpts(AST.getLangOpts()) {}
340 
341  HighlightingToken &addToken(SourceLocation Loc, HighlightingKind Kind) {
342  auto Range = getRangeForSourceLocation(Loc);
343  if (!Range)
344  return InvalidHighlightingToken;
345 
346  return addToken(*Range, Kind);
347  }
348 
349  HighlightingToken &addToken(Range R, HighlightingKind Kind) {
350  HighlightingToken HT;
351  HT.R = std::move(R);
352  HT.Kind = Kind;
353  Tokens.push_back(std::move(HT));
354  return Tokens.back();
355  }
356 
357  void addExtraModifier(SourceLocation Loc, HighlightingModifier Modifier) {
358  if (auto Range = getRangeForSourceLocation(Loc))
359  ExtraModifiers[*Range].push_back(Modifier);
360  }
361 
362  std::vector<HighlightingToken> collect(ParsedAST &AST) && {
363  // Initializer lists can give duplicates of tokens, therefore all tokens
364  // must be deduplicated.
365  llvm::sort(Tokens);
366  auto Last = std::unique(Tokens.begin(), Tokens.end());
367  Tokens.erase(Last, Tokens.end());
368 
369  // Macros can give tokens that have the same source range but conflicting
370  // kinds. In this case all tokens sharing this source range should be
371  // removed.
372  std::vector<HighlightingToken> NonConflicting;
373  NonConflicting.reserve(Tokens.size());
374  for (ArrayRef<HighlightingToken> TokRef = Tokens; !TokRef.empty();) {
375  ArrayRef<HighlightingToken> Conflicting =
376  TokRef.take_while([&](const HighlightingToken &T) {
377  // TokRef is guaranteed at least one element here because otherwise
378  // this predicate would never fire.
379  return T.R == TokRef.front().R;
380  });
381  if (auto Resolved = resolveConflict(Conflicting)) {
382  // Apply extra collected highlighting modifiers
383  auto Modifiers = ExtraModifiers.find(Resolved->R);
384  if (Modifiers != ExtraModifiers.end()) {
385  for (HighlightingModifier Mod : Modifiers->second) {
386  Resolved->addModifier(Mod);
387  }
388  }
389 
390  NonConflicting.push_back(*Resolved);
391  }
392  // TokRef[Conflicting.size()] is the next token with a different range (or
393  // the end of the Tokens).
394  TokRef = TokRef.drop_front(Conflicting.size());
395  }
396 
397  const auto &SM = AST.getSourceManager();
398  StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
399 
400  // Merge token stream with "inactive line" markers.
401  std::vector<HighlightingToken> WithInactiveLines;
402  auto SortedSkippedRanges = AST.getMacros().SkippedRanges;
403  llvm::sort(SortedSkippedRanges);
404  auto It = NonConflicting.begin();
405  for (const Range &R : SortedSkippedRanges) {
406  // Create one token for each line in the skipped range, so it works
407  // with line-based diffing.
408  assert(R.start.line <= R.end.line);
409  for (int Line = R.start.line; Line <= R.end.line; ++Line) {
410  // If the end of the inactive range is at the beginning
411  // of a line, that line is not inactive.
412  if (Line == R.end.line && R.end.character == 0)
413  continue;
414  // Copy tokens before the inactive line
415  for (; It != NonConflicting.end() && It->R.start.line < Line; ++It)
416  WithInactiveLines.push_back(std::move(*It));
417  // Add a token for the inactive line itself.
418  auto StartOfLine = positionToOffset(MainCode, Position{Line, 0});
419  if (StartOfLine) {
420  StringRef LineText =
421  MainCode.drop_front(*StartOfLine).take_until([](char C) {
422  return C == '\n';
423  });
424  HighlightingToken HT;
425  WithInactiveLines.emplace_back();
426  WithInactiveLines.back().Kind = HighlightingKind::InactiveCode;
427  WithInactiveLines.back().R.start.line = Line;
428  WithInactiveLines.back().R.end.line = Line;
429  WithInactiveLines.back().R.end.character =
430  static_cast<int>(lspLength(LineText));
431  } else {
432  elog("Failed to convert position to offset: {0}",
433  StartOfLine.takeError());
434  }
435 
436  // Skip any other tokens on the inactive line. e.g.
437  // `#ifndef Foo` is considered as part of an inactive region when Foo is
438  // defined, and there is a Foo macro token.
439  // FIXME: we should reduce the scope of the inactive region to not
440  // include the directive itself.
441  while (It != NonConflicting.end() && It->R.start.line == Line)
442  ++It;
443  }
444  }
445  // Copy tokens after the last inactive line
446  for (; It != NonConflicting.end(); ++It)
447  WithInactiveLines.push_back(std::move(*It));
448  return WithInactiveLines;
449  }
450 
451  const HeuristicResolver *getResolver() const { return Resolver; }
452 
453 private:
454  llvm::Optional<Range> getRangeForSourceLocation(SourceLocation Loc) {
455  Loc = getHighlightableSpellingToken(Loc, SourceMgr);
456  if (Loc.isInvalid())
457  return llvm::None;
458 
459  const auto *Tok = TB.spelledTokenAt(Loc);
460  assert(Tok);
461 
462  return halfOpenToRange(SourceMgr,
463  Tok->range(SourceMgr).toCharRange(SourceMgr));
464  }
465 
466  const syntax::TokenBuffer &TB;
467  const SourceManager &SourceMgr;
468  const LangOptions &LangOpts;
469  std::vector<HighlightingToken> Tokens;
470  std::map<Range, llvm::SmallVector<HighlightingModifier, 1>> ExtraModifiers;
471  const HeuristicResolver *Resolver;
472  // returned from addToken(InvalidLoc)
473  HighlightingToken InvalidHighlightingToken;
474 };
475 
476 llvm::Optional<HighlightingModifier> scopeModifier(const NamedDecl *D) {
477  const DeclContext *DC = D->getDeclContext();
478  // Injected "Foo" within the class "Foo" has file scope, not class scope.
479  if (auto *R = dyn_cast_or_null<RecordDecl>(D))
480  if (R->isInjectedClassName())
481  DC = DC->getParent();
482  // Lambda captures are considered function scope, not class scope.
483  if (llvm::isa<FieldDecl>(D))
484  if (const auto *RD = llvm::dyn_cast<RecordDecl>(DC))
485  if (RD->isLambda())
487  // Walk up the DeclContext hierarchy until we find something interesting.
488  for (; !DC->isFileContext(); DC = DC->getParent()) {
489  if (DC->isFunctionOrMethod())
491  if (DC->isRecord())
493  }
494  // Some template parameters (e.g. those for variable templates) don't have
495  // meaningful DeclContexts. That doesn't mean they're global!
496  if (DC->isTranslationUnit() && D->isTemplateParameter())
497  return llvm::None;
498  // ExternalLinkage threshold could be tweaked, e.g. module-visible as global.
499  if (D->getLinkageInternal() < ExternalLinkage)
502 }
503 
504 llvm::Optional<HighlightingModifier> scopeModifier(const Type *T) {
505  if (!T)
506  return llvm::None;
507  if (T->isBuiltinType())
509  if (auto *TD = dyn_cast<TemplateTypeParmType>(T))
510  return scopeModifier(TD->getDecl());
511  if (auto *TD = T->getAsTagDecl())
512  return scopeModifier(TD);
513  return llvm::None;
514 }
515 
516 /// Produces highlightings, which are not captured by findExplicitReferences,
517 /// e.g. highlights dependent names and 'auto' as the underlying type.
518 class CollectExtraHighlightings
519  : public RecursiveASTVisitor<CollectExtraHighlightings> {
520 public:
521  CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
522 
523  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
524  highlightMutableReferenceArguments(E->getConstructor(),
525  {E->getArgs(), E->getNumArgs()});
526 
527  return true;
528  }
529 
530  bool VisitCallExpr(CallExpr *E) {
531  // Highlighting parameters passed by non-const reference does not really
532  // make sense for literals...
533  if (isa<UserDefinedLiteral>(E))
534  return true;
535 
536  // FIXME ...here it would make sense though.
537  if (isa<CXXOperatorCallExpr>(E))
538  return true;
539 
540  highlightMutableReferenceArguments(
541  dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()),
542  {E->getArgs(), E->getNumArgs()});
543 
544  return true;
545  }
546 
547  void
548  highlightMutableReferenceArguments(const FunctionDecl *FD,
549  llvm::ArrayRef<const Expr *const> Args) {
550  if (!FD)
551  return;
552 
553  if (auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
554  // Iterate over the types of the function parameters.
555  // If any of them are non-const reference paramteres, add it as a
556  // highlighting modifier to the corresponding expression
557  for (size_t I = 0;
558  I < std::min(size_t(ProtoType->getNumParams()), Args.size()); ++I) {
559  auto T = ProtoType->getParamType(I);
560 
561  // Is this parameter passed by non-const reference?
562  // FIXME The condition !T->idDependentType() could be relaxed a bit,
563  // e.g. std::vector<T>& is dependent but we would want to highlight it
564  if (T->isLValueReferenceType() &&
565  !T.getNonReferenceType().isConstQualified() &&
566  !T->isDependentType()) {
567  if (auto *Arg = Args[I]) {
568  llvm::Optional<SourceLocation> Location;
569 
570  // FIXME Add "unwrapping" for ArraySubscriptExpr and UnaryOperator,
571  // e.g. highlight `a` in `a[i]`
572  // FIXME Handle dependent expression types
573  if (auto *DR = dyn_cast<DeclRefExpr>(Arg)) {
574  Location = DR->getLocation();
575  } else if (auto *M = dyn_cast<MemberExpr>(Arg)) {
576  Location = M->getMemberLoc();
577  }
578 
579  if (Location)
580  H.addExtraModifier(*Location,
582  }
583  }
584  }
585  }
586  }
587 
588  bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
589  if (auto K = kindForType(L.getTypePtr(), H.getResolver())) {
590  auto &Tok = H.addToken(L.getBeginLoc(), *K)
591  .addModifier(HighlightingModifier::Deduced);
592  if (auto Mod = scopeModifier(L.getTypePtr()))
593  Tok.addModifier(*Mod);
594  if (isDefaultLibrary(L.getTypePtr()))
595  Tok.addModifier(HighlightingModifier::DefaultLibrary);
596  }
597  return true;
598  }
599 
600  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
601  auto *AT = D->getType()->getContainedAutoType();
602  if (!AT)
603  return true;
604  if (auto K = kindForType(AT->getDeducedType().getTypePtrOrNull(),
605  H.getResolver())) {
606  auto &Tok = H.addToken(D->getTypeSpecStartLoc(), *K)
607  .addModifier(HighlightingModifier::Deduced);
608  const Type *Deduced = AT->getDeducedType().getTypePtrOrNull();
609  if (auto Mod = scopeModifier(Deduced))
610  Tok.addModifier(*Mod);
611  if (isDefaultLibrary(Deduced))
612  Tok.addModifier(HighlightingModifier::DefaultLibrary);
613  }
614  return true;
615  }
616 
617  // We handle objective-C selectors specially, because one reference can
618  // cover several non-contiguous tokens.
619  void highlightObjCSelector(const ArrayRef<SourceLocation> &Locs, bool Decl,
620  bool Class, bool DefaultLibrary) {
623  for (SourceLocation Part : Locs) {
624  auto &Tok =
625  H.addToken(Part, Kind).addModifier(HighlightingModifier::ClassScope);
626  if (Decl)
627  Tok.addModifier(HighlightingModifier::Declaration);
628  if (Class)
629  Tok.addModifier(HighlightingModifier::Static);
630  if (DefaultLibrary)
631  Tok.addModifier(HighlightingModifier::DefaultLibrary);
632  }
633  }
634 
635  bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
636  llvm::SmallVector<SourceLocation> Locs;
637  OMD->getSelectorLocs(Locs);
638  highlightObjCSelector(Locs, /*Decl=*/true, OMD->isClassMethod(),
639  isDefaultLibrary(OMD));
640  return true;
641  }
642 
643  bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
644  llvm::SmallVector<SourceLocation> Locs;
645  OME->getSelectorLocs(Locs);
646  bool DefaultLibrary = false;
647  if (ObjCMethodDecl *OMD = OME->getMethodDecl())
648  DefaultLibrary = isDefaultLibrary(OMD);
649  highlightObjCSelector(Locs, /*Decl=*/false, OME->isClassMessage(),
650  DefaultLibrary);
651  return true;
652  }
653 
654  // Objective-C allows you to use property syntax `self.prop` as sugar for
655  // `[self prop]` and `[self setProp:]` when there's no explicit `@property`
656  // for `prop` as well as for class properties. We treat this like a property
657  // even though semantically it's equivalent to a method expression.
658  void highlightObjCImplicitPropertyRef(const ObjCMethodDecl *OMD,
659  SourceLocation Loc) {
660  auto &Tok = H.addToken(Loc, HighlightingKind::Field)
661  .addModifier(HighlightingModifier::ClassScope);
662  if (OMD->isClassMethod())
663  Tok.addModifier(HighlightingModifier::Static);
664  if (isDefaultLibrary(OMD))
665  Tok.addModifier(HighlightingModifier::DefaultLibrary);
666  }
667 
668  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
669  // We need to handle implicit properties here since they will appear to
670  // reference `ObjCMethodDecl` via an implicit `ObjCMessageExpr`, so normal
671  // highlighting will not work.
672  if (!OPRE->isImplicitProperty())
673  return true;
674  // A single property expr can reference both a getter and setter, but we can
675  // only provide a single semantic token, so prefer the getter. In most cases
676  // the end result should be the same, although it's technically possible
677  // that the user defines a setter for a system SDK.
678  if (OPRE->isMessagingGetter()) {
679  highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
680  OPRE->getLocation());
681  return true;
682  }
683  if (OPRE->isMessagingSetter()) {
684  highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
685  OPRE->getLocation());
686  }
687  return true;
688  }
689 
690  bool VisitOverloadExpr(OverloadExpr *E) {
691  if (!E->decls().empty())
692  return true; // handled by findExplicitReferences.
693  auto &Tok = H.addToken(E->getNameLoc(), HighlightingKind::Unknown)
695  if (llvm::isa<UnresolvedMemberExpr>(E))
696  Tok.addModifier(HighlightingModifier::ClassScope);
697  // other case is UnresolvedLookupExpr, scope is unknown.
698  return true;
699  }
700 
701  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
702  H.addToken(E->getMemberNameInfo().getLoc(), HighlightingKind::Unknown)
704  .addModifier(HighlightingModifier::ClassScope);
705  return true;
706  }
707 
708  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
709  H.addToken(E->getNameInfo().getLoc(), HighlightingKind::Unknown)
711  .addModifier(HighlightingModifier::ClassScope);
712  return true;
713  }
714 
715  bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
716  H.addToken(L.getNameLoc(), HighlightingKind::Type)
718  .addModifier(HighlightingModifier::ClassScope);
719  return true;
720  }
721 
722  bool VisitDependentTemplateSpecializationTypeLoc(
723  DependentTemplateSpecializationTypeLoc L) {
724  H.addToken(L.getTemplateNameLoc(), HighlightingKind::Type)
726  .addModifier(HighlightingModifier::ClassScope);
727  return true;
728  }
729 
730  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
731  // Handle template template arguments only (other arguments are handled by
732  // their Expr, TypeLoc etc values).
733  if (L.getArgument().getKind() != TemplateArgument::Template &&
734  L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
735  return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
736 
737  TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
738  switch (N.getKind()) {
739  case TemplateName::OverloadedTemplate:
740  // Template template params must always be class templates.
741  // Don't bother to try to work out the scope here.
742  H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class);
743  break;
744  case TemplateName::DependentTemplate:
745  case TemplateName::AssumedTemplate:
746  H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class)
748  break;
749  case TemplateName::Template:
750  case TemplateName::QualifiedTemplate:
751  case TemplateName::SubstTemplateTemplateParm:
752  case TemplateName::SubstTemplateTemplateParmPack:
753  // Names that could be resolved to a TemplateDecl are handled elsewhere.
754  break;
755  }
756  return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
757  }
758 
759  // findExplicitReferences will walk nested-name-specifiers and
760  // find anything that can be resolved to a Decl. However, non-leaf
761  // components of nested-name-specifiers which are dependent names
762  // (kind "Identifier") cannot be resolved to a decl, so we visit
763  // them here.
764  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) {
765  if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) {
766  if (NNS->getKind() == NestedNameSpecifier::Identifier)
767  H.addToken(Q.getLocalBeginLoc(), HighlightingKind::Type)
769  .addModifier(HighlightingModifier::ClassScope);
770  }
771  return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q);
772  }
773 
774 private:
775  HighlightingsBuilder &H;
776 };
777 } // namespace
778 
779 std::vector<HighlightingToken> getSemanticHighlightings(ParsedAST &AST) {
780  auto &C = AST.getASTContext();
781  // Add highlightings for AST nodes.
782  HighlightingsBuilder Builder(AST);
783  // Highlight 'decltype' and 'auto' as their underlying types.
784  CollectExtraHighlightings(Builder).TraverseAST(C);
785  // Highlight all decls and references coming from the AST.
787  C,
788  [&](ReferenceLoc R) {
789  for (const NamedDecl *Decl : R.Targets) {
790  if (!canHighlightName(Decl->getDeclName()))
791  continue;
792  auto Kind = kindForDecl(Decl, AST.getHeuristicResolver());
793  if (!Kind)
794  continue;
795  auto &Tok = Builder.addToken(R.NameLoc, *Kind);
796 
797  // The attribute tests don't want to look at the template.
798  if (auto *TD = dyn_cast<TemplateDecl>(Decl)) {
799  if (auto *Templated = TD->getTemplatedDecl())
800  Decl = Templated;
801  }
802  if (auto Mod = scopeModifier(Decl))
803  Tok.addModifier(*Mod);
804  if (isConst(Decl))
805  Tok.addModifier(HighlightingModifier::Readonly);
806  if (isStatic(Decl))
807  Tok.addModifier(HighlightingModifier::Static);
808  if (isAbstract(Decl))
809  Tok.addModifier(HighlightingModifier::Abstract);
810  if (isVirtual(Decl))
811  Tok.addModifier(HighlightingModifier::Virtual);
812  if (isDependent(Decl))
813  Tok.addModifier(HighlightingModifier::DependentName);
814  if (isDefaultLibrary(Decl))
815  Tok.addModifier(HighlightingModifier::DefaultLibrary);
816  if (Decl->isDeprecated())
817  Tok.addModifier(HighlightingModifier::Deprecated);
818  // Do not treat an UnresolvedUsingValueDecl as a declaration.
819  // It's more common to think of it as a reference to the
820  // underlying declaration.
821  if (R.IsDecl && !isa<UnresolvedUsingValueDecl>(Decl))
822  Tok.addModifier(HighlightingModifier::Declaration);
823  }
824  },
825  AST.getHeuristicResolver());
826  // Add highlightings for macro references.
827  auto AddMacro = [&](const MacroOccurrence &M) {
828  auto &T = Builder.addToken(M.Rng, HighlightingKind::Macro);
829  T.addModifier(HighlightingModifier::GlobalScope);
830  if (M.IsDefinition)
831  T.addModifier(HighlightingModifier::Declaration);
832  };
833  for (const auto &SIDToRefs : AST.getMacros().MacroRefs)
834  for (const auto &M : SIDToRefs.second)
835  AddMacro(M);
836  for (const auto &M : AST.getMacros().UnknownMacros)
837  AddMacro(M);
838 
839  return std::move(Builder).collect(AST);
840 }
841 
842 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {
843  switch (K) {
844  case HighlightingKind::Variable:
845  return OS << "Variable";
846  case HighlightingKind::LocalVariable:
847  return OS << "LocalVariable";
848  case HighlightingKind::Parameter:
849  return OS << "Parameter";
850  case HighlightingKind::Function:
851  return OS << "Function";
852  case HighlightingKind::Method:
853  return OS << "Method";
854  case HighlightingKind::StaticMethod:
855  return OS << "StaticMethod";
856  case HighlightingKind::Field:
857  return OS << "Field";
858  case HighlightingKind::StaticField:
859  return OS << "StaticField";
860  case HighlightingKind::Class:
861  return OS << "Class";
862  case HighlightingKind::Interface:
863  return OS << "Interface";
864  case HighlightingKind::Enum:
865  return OS << "Enum";
866  case HighlightingKind::EnumConstant:
867  return OS << "EnumConstant";
868  case HighlightingKind::Typedef:
869  return OS << "Typedef";
871  return OS << "Type";
873  return OS << "Unknown";
874  case HighlightingKind::Namespace:
875  return OS << "Namespace";
876  case HighlightingKind::TemplateParameter:
877  return OS << "TemplateParameter";
878  case HighlightingKind::Concept:
879  return OS << "Concept";
880  case HighlightingKind::Primitive:
881  return OS << "Primitive";
882  case HighlightingKind::Macro:
883  return OS << "Macro";
884  case HighlightingKind::InactiveCode:
885  return OS << "InactiveCode";
886  }
887  llvm_unreachable("invalid HighlightingKind");
888 }
889 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K) {
890  switch (K) {
891  case HighlightingModifier::Declaration:
892  return OS << "decl"; // abbrevation for common case
893  default:
894  return OS << toSemanticTokenModifier(K);
895  }
896 }
897 
899  return std::tie(L.R, L.Kind, L.Modifiers) ==
900  std::tie(R.R, R.Kind, R.Modifiers);
901 }
903  return std::tie(L.R, L.Kind, R.Modifiers) <
904  std::tie(R.R, R.Kind, R.Modifiers);
905 }
906 
907 std::vector<SemanticToken>
908 toSemanticTokens(llvm::ArrayRef<HighlightingToken> Tokens) {
909  assert(std::is_sorted(Tokens.begin(), Tokens.end()));
910  std::vector<SemanticToken> Result;
911  const HighlightingToken *Last = nullptr;
912  for (const HighlightingToken &Tok : Tokens) {
913  Result.emplace_back();
914  SemanticToken &Out = Result.back();
915  // deltaStart/deltaLine are relative if possible.
916  if (Last) {
917  assert(Tok.R.start.line >= Last->R.start.line);
918  Out.deltaLine = Tok.R.start.line - Last->R.start.line;
919  if (Out.deltaLine == 0) {
920  assert(Tok.R.start.character >= Last->R.start.character);
921  Out.deltaStart = Tok.R.start.character - Last->R.start.character;
922  } else {
923  Out.deltaStart = Tok.R.start.character;
924  }
925  } else {
926  Out.deltaLine = Tok.R.start.line;
927  Out.deltaStart = Tok.R.start.character;
928  }
929  assert(Tok.R.end.line == Tok.R.start.line);
930  Out.length = Tok.R.end.character - Tok.R.start.character;
931  Out.tokenType = static_cast<unsigned>(Tok.Kind);
932  Out.tokenModifiers = Tok.Modifiers;
933 
934  Last = &Tok;
935  }
936  return Result;
937 }
939  switch (Kind) {
940  case HighlightingKind::Variable:
941  case HighlightingKind::LocalVariable:
942  case HighlightingKind::StaticField:
943  return "variable";
944  case HighlightingKind::Parameter:
945  return "parameter";
946  case HighlightingKind::Function:
947  return "function";
948  case HighlightingKind::Method:
949  return "method";
950  case HighlightingKind::StaticMethod:
951  // FIXME: better method with static modifier?
952  return "function";
953  case HighlightingKind::Field:
954  return "property";
955  case HighlightingKind::Class:
956  return "class";
957  case HighlightingKind::Interface:
958  return "interface";
959  case HighlightingKind::Enum:
960  return "enum";
961  case HighlightingKind::EnumConstant:
962  return "enumMember";
963  case HighlightingKind::Typedef:
965  return "type";
967  return "unknown"; // nonstandard
968  case HighlightingKind::Namespace:
969  return "namespace";
970  case HighlightingKind::TemplateParameter:
971  return "typeParameter";
972  case HighlightingKind::Concept:
973  return "concept"; // nonstandard
974  case HighlightingKind::Primitive:
975  return "type";
976  case HighlightingKind::Macro:
977  return "macro";
978  case HighlightingKind::InactiveCode:
979  return "comment";
980  }
981  llvm_unreachable("unhandled HighlightingKind");
982 }
983 
985  switch (Modifier) {
986  case HighlightingModifier::Declaration:
987  return "declaration";
989  return "deprecated";
990  case HighlightingModifier::Readonly:
991  return "readonly";
992  case HighlightingModifier::Static:
993  return "static";
994  case HighlightingModifier::Deduced:
995  return "deduced"; // nonstandard
996  case HighlightingModifier::Abstract:
997  return "abstract";
998  case HighlightingModifier::Virtual:
999  return "virtual";
1000  case HighlightingModifier::DependentName:
1001  return "dependentName"; // nonstandard
1002  case HighlightingModifier::DefaultLibrary:
1003  return "defaultLibrary";
1004  case HighlightingModifier::UsedAsMutableReference:
1005  return "usedAsMutableReference"; // nonstandard
1006  case HighlightingModifier::FunctionScope:
1007  return "functionScope"; // nonstandard
1008  case HighlightingModifier::ClassScope:
1009  return "classScope"; // nonstandard
1010  case HighlightingModifier::FileScope:
1011  return "fileScope"; // nonstandard
1012  case HighlightingModifier::GlobalScope:
1013  return "globalScope"; // nonstandard
1014  }
1015  llvm_unreachable("unhandled HighlightingModifier");
1016 }
1017 
1018 std::vector<SemanticTokensEdit>
1019 diffTokens(llvm::ArrayRef<SemanticToken> Old,
1020  llvm::ArrayRef<SemanticToken> New) {
1021  // For now, just replace everything from the first-last modification.
1022  // FIXME: use a real diff instead, this is bad with include-insertion.
1023 
1024  unsigned Offset = 0;
1025  while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1026  ++Offset;
1027  Old = Old.drop_front();
1028  New = New.drop_front();
1029  }
1030  while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1031  Old = Old.drop_back();
1032  New = New.drop_back();
1033  }
1034 
1035  if (Old.empty() && New.empty())
1036  return {};
1038  Edit.startToken = Offset;
1039  Edit.deleteTokens = Old.size();
1040  Edit.tokens = New;
1041  return {std::move(Edit)};
1042 }
1043 
1044 } // namespace clangd
1045 } // namespace clang
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
clang::clangd::HighlightingModifier::FunctionScope
@ FunctionScope
Loc
SourceLocation Loc
Definition: KernelNameRestrictionCheck.cpp:45
clang::clangd::HighlightingModifier::FileScope
@ FileScope
RecursiveASTVisitor
clang::clangd::HighlightingModifier
HighlightingModifier
Definition: SemanticHighlighting.h:61
clang::clangd::Edit
A set of edits generated for a single file.
Definition: SourceCode.h:180
clang::clangd::HighlightingToken::Modifiers
uint32_t Modifiers
Definition: SemanticHighlighting.h:88
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
Type
NodeType Type
Definition: HTMLGenerator.cpp:73
clang::clangd::CompletionItemKind::Class
@ Class
clang::clangd::HighlightingKind::Primitive
@ Primitive
Location
Definition: Modularize.cpp:382
clang::doc::MD
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
clang::clangd::toSemanticTokenModifier
llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier)
Definition: SemanticHighlighting.cpp:984
clang::clangd::HighlightingModifier::Deduced
@ Deduced
clang::clangd::ParsedAST::getASTContext
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
Definition: ParsedAST.cpp:532
clang::clangd::SemanticTokensEdit
Describes a a replacement of a contiguous range of semanticTokens.
Definition: Protocol.h:1627
clang::clangd::lspLength
size_t lspLength(llvm::StringRef Code)
Definition: SourceCode.cpp:151
clang::clangd::HighlightingToken::R
Range R
Definition: SemanticHighlighting.h:89
Kind
BindArgumentKind Kind
Definition: AvoidBindCheck.cpp:59
clang::clangd::Range::start
Position start
The range's start position.
Definition: Protocol.h:179
clang::clangd::HighlightingKind
HighlightingKind
Definition: SemanticHighlighting.h:30
clang::clangd::HighlightingKind::Typedef
@ Typedef
clang::clangd::MainFileMacros::MacroRefs
llvm::DenseMap< SymbolID, std::vector< MacroOccurrence > > MacroRefs
Definition: CollectMacros.h:33
clang::clangd::HighlightingToken::Kind
HighlightingKind Kind
Definition: SemanticHighlighting.h:87
SourceMgr
llvm::SourceMgr * SourceMgr
Definition: ConfigCompile.cpp:102
clang::clangd::HighlightingKind::TemplateParameter
@ TemplateParameter
clang::clangd::operator<
bool operator<(const HighlightingToken &L, const HighlightingToken &R)
Definition: SemanticHighlighting.cpp:902
FindTarget.h
Target
std::string Target
Definition: QueryDriverDatabase.cpp:64
clang::clangd::HighlightingModifier::Virtual
@ Virtual
clang::clangd::HighlightingKind::Macro
@ Macro
clang::clangd::Position::line
int line
Line position in a document (zero-based).
Definition: Protocol.h:150
clang::clangd::HighlightingKind::Variable
@ Variable
clang::clangd::HighlightingKind::InactiveCode
@ InactiveCode
Protocol.h
M
const google::protobuf::Message & M
Definition: Server.cpp:309
Offset
size_t Offset
Definition: CodeComplete.cpp:1103
clang::clangd::halfOpenToRange
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
Definition: SourceCode.cpp:466
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
clang::clangd::HighlightingKind::Function
@ Function
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:100
clang::clangd::Unknown
@ Unknown
Definition: FuzzyMatch.h:56
Line
int Line
Definition: PreprocessorTracker.cpp:514
clang::clangd::SemanticToken
Specifies a single semantic token in the document.
Definition: Protocol.h:1579
clang::clangd::diffTokens
std::vector< SemanticTokensEdit > diffTokens(llvm::ArrayRef< SemanticToken > Old, llvm::ArrayRef< SemanticToken > New)
Definition: SemanticHighlighting.cpp:1019
clang::clangd::HighlightingKind::Unknown
@ Unknown
Builder
CodeCompletionBuilder Builder
Definition: CodeCompletionStringsTests.cpp:36
Logger.h
Args
llvm::json::Object Args
Definition: Trace.cpp:139
clang::clangd::positionToOffset
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:175
if
if(CLANGD_ENABLE_REMOTE) generate_protos(RemoteIndexProto "Index.proto") generate_protos(MonitoringServiceProto "MonitoringService.proto" GRPC) generate_protos(RemoteIndexServiceProto "Service.proto" DEPENDS "Index.proto" GRPC) target_link_libraries(RemoteIndexServiceProto PRIVATE RemoteIndexProto MonitoringServiceProto) include_directories($
Definition: clangd/index/remote/CMakeLists.txt:1
clang::clangd::HighlightingKind::Namespace
@ Namespace
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:27
clang::clangd::HighlightingKind::Type
@ Type
clang::clangd::HighlightingKind::Concept
@ Concept
clang::clangd::HighlightingKind::LocalVariable
@ LocalVariable
clang::clangd::HighlightingModifier::Deprecated
@ Deprecated
clang::clangd::Position::character
int character
Character offset on a line in a document (zero-based).
Definition: Protocol.h:155
clang::clangd::HeuristicResolver::resolveUsingValueDecl
std::vector< const NamedDecl * > resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const
Definition: HeuristicResolver.cpp:165
clang::clangd::HighlightingModifier::Abstract
@ Abstract
clang::clangd::HighlightingModifier::GlobalScope
@ GlobalScope
clang::clangd::ParsedAST::getHeuristicResolver
const HeuristicResolver * getHeuristicResolver() const
Definition: ParsedAST.h:115
clang::clangd::DeclRelation::Underlying
@ Underlying
This is the underlying declaration for a renaming-alias, decltype etc.
clang::clangd::HighlightingKind::Enum
@ Enum
clang::clangd::getSemanticHighlightings
std::vector< HighlightingToken > getSemanticHighlightings(ParsedAST &AST)
Definition: SemanticHighlighting.cpp:779
clang::clangd::HighlightingKind::Method
@ Method
clang::clangd::Deprecated
@ Deprecated
Deprecated or obsolete code.
Definition: Protocol.h:824
SourceCode.h
HeuristicResolver.h
clang::clangd::operator==
bool operator==(const HighlightingToken &L, const HighlightingToken &R)
Definition: SemanticHighlighting.cpp:898
clang::clangd::HighlightingModifier::Static
@ Static
clang::clangd::HighlightingKind::Parameter
@ Parameter
clang::clangd::ReferenceLoc
Information about a reference written in the source code, independent of the actual AST node that thi...
Definition: FindTarget.h:129
clang::clangd::HighlightingToken
Definition: SemanticHighlighting.h:86
clang::clangd::toSemanticTokens
std::vector< SemanticToken > toSemanticTokens(llvm::ArrayRef< HighlightingToken > Tokens)
Definition: SemanticHighlighting.cpp:908
clang::clangd::HighlightingKind::StaticMethod
@ StaticMethod
C
const Criteria C
Definition: FunctionCognitiveComplexityCheck.cpp:93
clang::clangd::toSemanticTokenType
llvm::StringRef toSemanticTokenType(HighlightingKind Kind)
Definition: SemanticHighlighting.cpp:938
SemanticHighlighting.h
clang::clangd::HighlightingModifier::DefaultLibrary
@ DefaultLibrary
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
OS
llvm::raw_string_ostream OS
Definition: TraceTests.cpp:163
clang::clangd::HighlightingKind::Interface
@ Interface
clang::clangd::HighlightingKind::StaticField
@ StaticField
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, HighlightingModifier K)
Definition: SemanticHighlighting.cpp:889
clang::clangd::ReferenceLoc::IsDecl
bool IsDecl
True if the reference is a declaration or definition;.
Definition: FindTarget.h:135
clang::clangd::ParsedAST
Stores and provides access to parsed AST.
Definition: ParsedAST.h:49
clang::clangd::HighlightingKind::EnumConstant
@ EnumConstant
clang::clangd::MainFileMacros::UnknownMacros
std::vector< MacroOccurrence > UnknownMacros
Definition: CollectMacros.h:37
Out
CompiledFragmentImpl & Out
Definition: ConfigCompile.cpp:100
clang::clangd::elog
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:62
clang::clangd::findExplicitReferences
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out, const HeuristicResolver *Resolver)
Recursively traverse S and report all references explicitly written in the code.
Definition: FindTarget.cpp:1114
clang::clangd::HighlightingKind::Field
@ Field
clang::clangd::HighlightingKind::Class
@ Class
clang::clangd::ReferenceLoc::Targets
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Definition: FindTarget.h:141
clang::clangd::HighlightingModifier::Readonly
@ Readonly
K
Kind K
Definition: Rename.cpp:442
clang::clangd::HighlightingModifier::DependentName
@ DependentName
clang::clangd::HighlightingModifier::UsedAsMutableReference
@ UsedAsMutableReference
clang::clangd::HighlightingModifier::ClassScope
@ ClassScope
ParsedAST.h
clang::clangd::HighlightingModifier::Declaration
@ Declaration
clang::clangd::ParsedAST::getMacros
const MainFileMacros & getMacros() const
Gets all macro references (definition, expansions) present in the main file, including those in the p...
Definition: ParsedAST.cpp:552