blob: bf0e78616b349c7f01d516e10e6e42f43f49bb47 [file] [log] [blame]
Haojian Wu5f100262018-03-09 14:00:34 +00001//===--- AST.cpp - Utility AST functions -----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "AST.h"
11
12#include "clang/AST/ASTContext.h"
13#include "clang/AST/Decl.h"
Eric Liu48597382018-10-18 12:23:05 +000014#include "clang/Basic/SourceLocation.h"
Haojian Wu5f100262018-03-09 14:00:34 +000015#include "clang/Basic/SourceManager.h"
Haojian Wuc6ddb462018-08-07 08:57:52 +000016#include "clang/Index/USRGeneration.h"
Haojian Wu5f100262018-03-09 14:00:34 +000017
Sam McCallc008af62018-10-20 15:30:37 +000018using namespace llvm;
Haojian Wu5f100262018-03-09 14:00:34 +000019namespace clang {
20namespace clangd {
Haojian Wu5f100262018-03-09 14:00:34 +000021
Eric Liu48597382018-10-18 12:23:05 +000022// Returns true if the complete name of decl \p D is spelled in the source code.
23// This is not the case for
24// * symbols formed via macro concatenation, the spelling location will
25// be "<scratch space>"
26// * symbols controlled and defined by a compile command-line option
27// `-DName=foo`, the spelling location will be "<command line>".
28bool isSpelledInSourceCode(const Decl *D) {
29 const auto &SM = D->getASTContext().getSourceManager();
30 auto Loc = D->getLocation();
Haojian Wu5f100262018-03-09 14:00:34 +000031 // FIXME: Revisit the strategy, the heuristic is limitted when handling
32 // macros, we should use the location where the whole definition occurs.
Eric Liu48597382018-10-18 12:23:05 +000033 if (Loc.isMacroID()) {
34 std::string PrintLoc = SM.getSpellingLoc(Loc).printToString(SM);
Sam McCallc008af62018-10-20 15:30:37 +000035 if (StringRef(PrintLoc).startswith("<scratch") ||
36 StringRef(PrintLoc).startswith("<command line>"))
Eric Liu48597382018-10-18 12:23:05 +000037 return false;
Haojian Wu5f100262018-03-09 14:00:34 +000038 }
Eric Liu48597382018-10-18 12:23:05 +000039 return true;
40}
41
42bool isImplementationDetail(const Decl *D) { return !isSpelledInSourceCode(D); }
43
44SourceLocation findNameLoc(const clang::Decl* D) {
45 const auto &SM = D->getASTContext().getSourceManager();
46 if (!isSpelledInSourceCode(D))
47 // Use the expansion location as spelling location is not interesting.
48 return SM.getExpansionRange(D->getLocation()).getBegin();
49 return SM.getSpellingLoc(D->getLocation());
Haojian Wu5f100262018-03-09 14:00:34 +000050}
51
Eric Liu7ad16962018-06-22 10:46:59 +000052std::string printQualifiedName(const NamedDecl &ND) {
53 std::string QName;
Sam McCallc008af62018-10-20 15:30:37 +000054 raw_string_ostream OS(QName);
Eric Liu7ad16962018-06-22 10:46:59 +000055 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
56 // Note that inline namespaces are treated as transparent scopes. This
57 // reflects the way they're most commonly used for lookup. Ideally we'd
58 // include them, but at query time it's hard to find all the inline
59 // namespaces to query: the preamble doesn't have a dedicated list.
60 Policy.SuppressUnwrittenScope = true;
61 ND.printQualifiedName(OS, Policy);
62 OS.flush();
63 assert(!StringRef(QName).startswith("::"));
64 return QName;
65}
66
Eric Liu3fac4ef2018-10-17 11:19:02 +000067std::string printNamespaceScope(const DeclContext &DC) {
68 for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent())
69 if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx))
70 if (!NS->isAnonymousNamespace() && !NS->isInlineNamespace())
71 return printQualifiedName(*NS) + "::";
72 return "";
73}
74
Sam McCallc008af62018-10-20 15:30:37 +000075Optional<SymbolID> getSymbolID(const Decl *D) {
76 SmallString<128> USR;
Haojian Wuc6ddb462018-08-07 08:57:52 +000077 if (index::generateUSRForDecl(D, USR))
78 return None;
79 return SymbolID(USR);
80}
81
Sam McCallc008af62018-10-20 15:30:37 +000082Optional<SymbolID> getSymbolID(const IdentifierInfo &II, const MacroInfo *MI,
83 const SourceManager &SM) {
Eric Liud25f1212018-09-06 09:59:37 +000084 if (MI == nullptr)
85 return None;
Sam McCallc008af62018-10-20 15:30:37 +000086 SmallString<128> USR;
Eric Liud25f1212018-09-06 09:59:37 +000087 if (index::generateUSRForMacro(II.getName(), MI->getDefinitionLoc(), SM, USR))
88 return None;
89 return SymbolID(USR);
90}
91
Haojian Wu5f100262018-03-09 14:00:34 +000092} // namespace clangd
93} // namespace clang