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 = nullptr;
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  auto K =
605  kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
606  if (!K)
607  return true;
608  SourceLocation StartLoc = D->getTypeSpecStartLoc();
609  // The AutoType may not have a corresponding token, e.g. in the case of
610  // init-captures. In this case, StartLoc overlaps with the location
611  // of the decl itself, and producing a token for the type here would result
612  // in both it and the token for the decl being dropped due to conflict.
613  if (StartLoc == D->getLocation())
614  return true;
615  auto &Tok =
616  H.addToken(StartLoc, *K).addModifier(HighlightingModifier::Deduced);
617  const Type *Deduced = AT->getDeducedType().getTypePtrOrNull();
618  if (auto Mod = scopeModifier(Deduced))
619  Tok.addModifier(*Mod);
620  if (isDefaultLibrary(Deduced))
621  Tok.addModifier(HighlightingModifier::DefaultLibrary);
622  return true;
623  }
624 
625  // We handle objective-C selectors specially, because one reference can
626  // cover several non-contiguous tokens.
627  void highlightObjCSelector(const ArrayRef<SourceLocation> &Locs, bool Decl,
628  bool Class, bool DefaultLibrary) {
631  for (SourceLocation Part : Locs) {
632  auto &Tok =
633  H.addToken(Part, Kind).addModifier(HighlightingModifier::ClassScope);
634  if (Decl)
635  Tok.addModifier(HighlightingModifier::Declaration);
636  if (Class)
637  Tok.addModifier(HighlightingModifier::Static);
638  if (DefaultLibrary)
639  Tok.addModifier(HighlightingModifier::DefaultLibrary);
640  }
641  }
642 
643  bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
644  llvm::SmallVector<SourceLocation> Locs;
645  OMD->getSelectorLocs(Locs);
646  highlightObjCSelector(Locs, /*Decl=*/true, OMD->isClassMethod(),
647  isDefaultLibrary(OMD));
648  return true;
649  }
650 
651  bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
652  llvm::SmallVector<SourceLocation> Locs;
653  OME->getSelectorLocs(Locs);
654  bool DefaultLibrary = false;
655  if (ObjCMethodDecl *OMD = OME->getMethodDecl())
656  DefaultLibrary = isDefaultLibrary(OMD);
657  highlightObjCSelector(Locs, /*Decl=*/false, OME->isClassMessage(),
658  DefaultLibrary);
659  return true;
660  }
661 
662  // Objective-C allows you to use property syntax `self.prop` as sugar for
663  // `[self prop]` and `[self setProp:]` when there's no explicit `@property`
664  // for `prop` as well as for class properties. We treat this like a property
665  // even though semantically it's equivalent to a method expression.
666  void highlightObjCImplicitPropertyRef(const ObjCMethodDecl *OMD,
667  SourceLocation Loc) {
668  auto &Tok = H.addToken(Loc, HighlightingKind::Field)
669  .addModifier(HighlightingModifier::ClassScope);
670  if (OMD->isClassMethod())
671  Tok.addModifier(HighlightingModifier::Static);
672  if (isDefaultLibrary(OMD))
673  Tok.addModifier(HighlightingModifier::DefaultLibrary);
674  }
675 
676  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
677  // We need to handle implicit properties here since they will appear to
678  // reference `ObjCMethodDecl` via an implicit `ObjCMessageExpr`, so normal
679  // highlighting will not work.
680  if (!OPRE->isImplicitProperty())
681  return true;
682  // A single property expr can reference both a getter and setter, but we can
683  // only provide a single semantic token, so prefer the getter. In most cases
684  // the end result should be the same, although it's technically possible
685  // that the user defines a setter for a system SDK.
686  if (OPRE->isMessagingGetter()) {
687  highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
688  OPRE->getLocation());
689  return true;
690  }
691  if (OPRE->isMessagingSetter()) {
692  highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
693  OPRE->getLocation());
694  }
695  return true;
696  }
697 
698  bool VisitOverloadExpr(OverloadExpr *E) {
699  if (!E->decls().empty())
700  return true; // handled by findExplicitReferences.
701  auto &Tok = H.addToken(E->getNameLoc(), HighlightingKind::Unknown)
703  if (llvm::isa<UnresolvedMemberExpr>(E))
704  Tok.addModifier(HighlightingModifier::ClassScope);
705  // other case is UnresolvedLookupExpr, scope is unknown.
706  return true;
707  }
708 
709  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
710  H.addToken(E->getMemberNameInfo().getLoc(), HighlightingKind::Unknown)
712  .addModifier(HighlightingModifier::ClassScope);
713  return true;
714  }
715 
716  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
717  H.addToken(E->getNameInfo().getLoc(), HighlightingKind::Unknown)
719  .addModifier(HighlightingModifier::ClassScope);
720  return true;
721  }
722 
723  bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
724  H.addToken(L.getNameLoc(), HighlightingKind::Type)
726  .addModifier(HighlightingModifier::ClassScope);
727  return true;
728  }
729 
730  bool VisitDependentTemplateSpecializationTypeLoc(
731  DependentTemplateSpecializationTypeLoc L) {
732  H.addToken(L.getTemplateNameLoc(), HighlightingKind::Type)
734  .addModifier(HighlightingModifier::ClassScope);
735  return true;
736  }
737 
738  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
739  // Handle template template arguments only (other arguments are handled by
740  // their Expr, TypeLoc etc values).
741  if (L.getArgument().getKind() != TemplateArgument::Template &&
742  L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
743  return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
744 
745  TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
746  switch (N.getKind()) {
747  case TemplateName::OverloadedTemplate:
748  // Template template params must always be class templates.
749  // Don't bother to try to work out the scope here.
750  H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class);
751  break;
752  case TemplateName::DependentTemplate:
753  case TemplateName::AssumedTemplate:
754  H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class)
756  break;
757  case TemplateName::Template:
758  case TemplateName::QualifiedTemplate:
759  case TemplateName::SubstTemplateTemplateParm:
760  case TemplateName::SubstTemplateTemplateParmPack:
761  // Names that could be resolved to a TemplateDecl are handled elsewhere.
762  break;
763  }
764  return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
765  }
766 
767  // findExplicitReferences will walk nested-name-specifiers and
768  // find anything that can be resolved to a Decl. However, non-leaf
769  // components of nested-name-specifiers which are dependent names
770  // (kind "Identifier") cannot be resolved to a decl, so we visit
771  // them here.
772  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) {
773  if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) {
774  if (NNS->getKind() == NestedNameSpecifier::Identifier)
775  H.addToken(Q.getLocalBeginLoc(), HighlightingKind::Type)
777  .addModifier(HighlightingModifier::ClassScope);
778  }
779  return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q);
780  }
781 
782 private:
783  HighlightingsBuilder &H;
784 };
785 } // namespace
786 
787 std::vector<HighlightingToken> getSemanticHighlightings(ParsedAST &AST) {
788  auto &C = AST.getASTContext();
789  // Add highlightings for AST nodes.
790  HighlightingsBuilder Builder(AST);
791  // Highlight 'decltype' and 'auto' as their underlying types.
792  CollectExtraHighlightings(Builder).TraverseAST(C);
793  // Highlight all decls and references coming from the AST.
795  C,
796  [&](ReferenceLoc R) {
797  for (const NamedDecl *Decl : R.Targets) {
798  if (!canHighlightName(Decl->getDeclName()))
799  continue;
800  auto Kind = kindForDecl(Decl, AST.getHeuristicResolver());
801  if (!Kind)
802  continue;
803  auto &Tok = Builder.addToken(R.NameLoc, *Kind);
804 
805  // The attribute tests don't want to look at the template.
806  if (auto *TD = dyn_cast<TemplateDecl>(Decl)) {
807  if (auto *Templated = TD->getTemplatedDecl())
808  Decl = Templated;
809  }
810  if (auto Mod = scopeModifier(Decl))
811  Tok.addModifier(*Mod);
812  if (isConst(Decl))
813  Tok.addModifier(HighlightingModifier::Readonly);
814  if (isStatic(Decl))
815  Tok.addModifier(HighlightingModifier::Static);
816  if (isAbstract(Decl))
817  Tok.addModifier(HighlightingModifier::Abstract);
818  if (isVirtual(Decl))
819  Tok.addModifier(HighlightingModifier::Virtual);
820  if (isDependent(Decl))
821  Tok.addModifier(HighlightingModifier::DependentName);
822  if (isDefaultLibrary(Decl))
823  Tok.addModifier(HighlightingModifier::DefaultLibrary);
824  if (Decl->isDeprecated())
825  Tok.addModifier(HighlightingModifier::Deprecated);
826  // Do not treat an UnresolvedUsingValueDecl as a declaration.
827  // It's more common to think of it as a reference to the
828  // underlying declaration.
829  if (R.IsDecl && !isa<UnresolvedUsingValueDecl>(Decl))
830  Tok.addModifier(HighlightingModifier::Declaration);
831  }
832  },
833  AST.getHeuristicResolver());
834  // Add highlightings for macro references.
835  auto AddMacro = [&](const MacroOccurrence &M) {
836  auto &T = Builder.addToken(M.Rng, HighlightingKind::Macro);
837  T.addModifier(HighlightingModifier::GlobalScope);
838  if (M.IsDefinition)
839  T.addModifier(HighlightingModifier::Declaration);
840  };
841  for (const auto &SIDToRefs : AST.getMacros().MacroRefs)
842  for (const auto &M : SIDToRefs.second)
843  AddMacro(M);
844  for (const auto &M : AST.getMacros().UnknownMacros)
845  AddMacro(M);
846 
847  return std::move(Builder).collect(AST);
848 }
849 
850 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {
851  switch (K) {
852  case HighlightingKind::Variable:
853  return OS << "Variable";
854  case HighlightingKind::LocalVariable:
855  return OS << "LocalVariable";
856  case HighlightingKind::Parameter:
857  return OS << "Parameter";
858  case HighlightingKind::Function:
859  return OS << "Function";
860  case HighlightingKind::Method:
861  return OS << "Method";
862  case HighlightingKind::StaticMethod:
863  return OS << "StaticMethod";
864  case HighlightingKind::Field:
865  return OS << "Field";
866  case HighlightingKind::StaticField:
867  return OS << "StaticField";
868  case HighlightingKind::Class:
869  return OS << "Class";
870  case HighlightingKind::Interface:
871  return OS << "Interface";
872  case HighlightingKind::Enum:
873  return OS << "Enum";
874  case HighlightingKind::EnumConstant:
875  return OS << "EnumConstant";
876  case HighlightingKind::Typedef:
877  return OS << "Typedef";
879  return OS << "Type";
881  return OS << "Unknown";
882  case HighlightingKind::Namespace:
883  return OS << "Namespace";
884  case HighlightingKind::TemplateParameter:
885  return OS << "TemplateParameter";
886  case HighlightingKind::Concept:
887  return OS << "Concept";
888  case HighlightingKind::Primitive:
889  return OS << "Primitive";
890  case HighlightingKind::Macro:
891  return OS << "Macro";
892  case HighlightingKind::InactiveCode:
893  return OS << "InactiveCode";
894  }
895  llvm_unreachable("invalid HighlightingKind");
896 }
897 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K) {
898  switch (K) {
899  case HighlightingModifier::Declaration:
900  return OS << "decl"; // abbrevation for common case
901  default:
902  return OS << toSemanticTokenModifier(K);
903  }
904 }
905 
907  return std::tie(L.R, L.Kind, L.Modifiers) ==
908  std::tie(R.R, R.Kind, R.Modifiers);
909 }
911  return std::tie(L.R, L.Kind, R.Modifiers) <
912  std::tie(R.R, R.Kind, R.Modifiers);
913 }
914 
915 std::vector<SemanticToken>
916 toSemanticTokens(llvm::ArrayRef<HighlightingToken> Tokens) {
917  assert(std::is_sorted(Tokens.begin(), Tokens.end()));
918  std::vector<SemanticToken> Result;
919  const HighlightingToken *Last = nullptr;
920  for (const HighlightingToken &Tok : Tokens) {
921  Result.emplace_back();
922  SemanticToken &Out = Result.back();
923  // deltaStart/deltaLine are relative if possible.
924  if (Last) {
925  assert(Tok.R.start.line >= Last->R.start.line);
926  Out.deltaLine = Tok.R.start.line - Last->R.start.line;
927  if (Out.deltaLine == 0) {
928  assert(Tok.R.start.character >= Last->R.start.character);
929  Out.deltaStart = Tok.R.start.character - Last->R.start.character;
930  } else {
931  Out.deltaStart = Tok.R.start.character;
932  }
933  } else {
934  Out.deltaLine = Tok.R.start.line;
935  Out.deltaStart = Tok.R.start.character;
936  }
937  assert(Tok.R.end.line == Tok.R.start.line);
938  Out.length = Tok.R.end.character - Tok.R.start.character;
939  Out.tokenType = static_cast<unsigned>(Tok.Kind);
940  Out.tokenModifiers = Tok.Modifiers;
941 
942  Last = &Tok;
943  }
944  return Result;
945 }
947  switch (Kind) {
948  case HighlightingKind::Variable:
949  case HighlightingKind::LocalVariable:
950  case HighlightingKind::StaticField:
951  return "variable";
952  case HighlightingKind::Parameter:
953  return "parameter";
954  case HighlightingKind::Function:
955  return "function";
956  case HighlightingKind::Method:
957  return "method";
958  case HighlightingKind::StaticMethod:
959  // FIXME: better method with static modifier?
960  return "function";
961  case HighlightingKind::Field:
962  return "property";
963  case HighlightingKind::Class:
964  return "class";
965  case HighlightingKind::Interface:
966  return "interface";
967  case HighlightingKind::Enum:
968  return "enum";
969  case HighlightingKind::EnumConstant:
970  return "enumMember";
971  case HighlightingKind::Typedef:
973  return "type";
975  return "unknown"; // nonstandard
976  case HighlightingKind::Namespace:
977  return "namespace";
978  case HighlightingKind::TemplateParameter:
979  return "typeParameter";
980  case HighlightingKind::Concept:
981  return "concept"; // nonstandard
982  case HighlightingKind::Primitive:
983  return "type";
984  case HighlightingKind::Macro:
985  return "macro";
986  case HighlightingKind::InactiveCode:
987  return "comment";
988  }
989  llvm_unreachable("unhandled HighlightingKind");
990 }
991 
993  switch (Modifier) {
994  case HighlightingModifier::Declaration:
995  return "declaration";
997  return "deprecated";
998  case HighlightingModifier::Readonly:
999  return "readonly";
1000  case HighlightingModifier::Static:
1001  return "static";
1002  case HighlightingModifier::Deduced:
1003  return "deduced"; // nonstandard
1004  case HighlightingModifier::Abstract:
1005  return "abstract";
1006  case HighlightingModifier::Virtual:
1007  return "virtual";
1008  case HighlightingModifier::DependentName:
1009  return "dependentName"; // nonstandard
1010  case HighlightingModifier::DefaultLibrary:
1011  return "defaultLibrary";
1012  case HighlightingModifier::UsedAsMutableReference:
1013  return "usedAsMutableReference"; // nonstandard
1014  case HighlightingModifier::FunctionScope:
1015  return "functionScope"; // nonstandard
1016  case HighlightingModifier::ClassScope:
1017  return "classScope"; // nonstandard
1018  case HighlightingModifier::FileScope:
1019  return "fileScope"; // nonstandard
1020  case HighlightingModifier::GlobalScope:
1021  return "globalScope"; // nonstandard
1022  }
1023  llvm_unreachable("unhandled HighlightingModifier");
1024 }
1025 
1026 std::vector<SemanticTokensEdit>
1027 diffTokens(llvm::ArrayRef<SemanticToken> Old,
1028  llvm::ArrayRef<SemanticToken> New) {
1029  // For now, just replace everything from the first-last modification.
1030  // FIXME: use a real diff instead, this is bad with include-insertion.
1031 
1032  unsigned Offset = 0;
1033  while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1034  ++Offset;
1035  Old = Old.drop_front();
1036  New = New.drop_front();
1037  }
1038  while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1039  Old = Old.drop_back();
1040  New = New.drop_back();
1041  }
1042 
1043  if (Old.empty() && New.empty())
1044  return {};
1046  Edit.startToken = Offset;
1047  Edit.deleteTokens = Old.size();
1048  Edit.tokens = New;
1049  return {std::move(Edit)};
1050 }
1051 
1052 } // namespace clangd
1053 } // 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:184
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:992
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:632
clang::clangd::SemanticTokensEdit
Describes a a replacement of a contiguous range of semanticTokens.
Definition: Protocol.h:1650
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:184
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:910
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:155
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:1192
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:1602
clang::clangd::diffTokens
std::vector< SemanticTokensEdit > diffTokens(llvm::ArrayRef< SemanticToken > Old, llvm::ArrayRef< SemanticToken > New)
Definition: SemanticHighlighting.cpp:1027
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:28
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:160
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:117
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:787
clang::clangd::HighlightingKind::Method
@ Method
clang::clangd::Deprecated
@ Deprecated
Deprecated or obsolete code.
Definition: Protocol.h:834
SourceCode.h
HeuristicResolver.h
clang::clangd::operator==
bool operator==(const HighlightingToken &L, const HighlightingToken &R)
Definition: SemanticHighlighting.cpp:906
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:916
clang::clangd::HighlightingKind::StaticMethod
@ StaticMethod
C
const Criteria C
Definition: FunctionCognitiveComplexityCheck.cpp:93
clang::clangd::toSemanticTokenType
llvm::StringRef toSemanticTokenType(HighlightingKind Kind)
Definition: SemanticHighlighting.cpp:946
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:897
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:1129
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:436
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:652