On 11/26/18 12:41 PM, Ilya Biryukov wrote: > Sorry about that, should be fixed in r347539. >
Yep, thanks! /Mikael > On Mon, Nov 26, 2018 at 8:10 AM Mikael Holmén > <mikael.hol...@ericsson.com <mailto:mikael.hol...@ericsson.com>> wrote: > > Hi Ilya, > > This patch doesn't compile for me with clang 3.6.0. I get: > > ../tools/clang/tools/extra/clangd/Protocol.cpp:474:10: error: no viable > conversion from 'json::Object' to 'llvm::json::Value' > return Result; > ^~~~~~ > ../include/llvm/Support/JSON.h:291:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'const > llvm::json::Value &' for 1st argument > Value(const Value &M) { copyFrom(M); } > ^ > ../include/llvm/Support/JSON.h:292:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'llvm::json::Value > &&' for 1st argument > Value(Value &&M) { moveFrom(std::move(M)); } > ^ > ../include/llvm/Support/JSON.h:293:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to > 'std::initializer_list<Value>' for 1st argument > Value(std::initializer_list<Value> Elements); > ^ > ../include/llvm/Support/JSON.h:294:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'json::Array &&' for > 1st argument > Value(json::Array &&Elements) : Type(T_Array) { > ^ > ../include/llvm/Support/JSON.h:299:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'json::Object &&' > for > 1st argument > Value(json::Object &&Properties) : Type(T_Object) { > ^ > ../include/llvm/Support/JSON.h:305:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'std::string' (aka > 'basic_string<char>') for 1st argument > Value(std::string V) : Type(T_String) { > ^ > ../include/llvm/Support/JSON.h:312:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'const > llvm::SmallVectorImpl<char> &' for 1st argument > Value(const llvm::SmallVectorImpl<char> &V) > ^ > ../include/llvm/Support/JSON.h:314:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'const > llvm::formatv_object_base &' for 1st argument > Value(const llvm::formatv_object_base &V) : Value(V.str()){}; > ^ > ../include/llvm/Support/JSON.h:316:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'llvm::StringRef' > for > 1st argument > Value(StringRef V) : Type(T_StringRef) { > ^ > ../include/llvm/Support/JSON.h:323:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'const char *' for > 1st argument > Value(const char *V) : Value(StringRef(V)) {} > ^ > ../include/llvm/Support/JSON.h:324:3: note: candidate constructor not > viable: no known conversion from 'json::Object' to 'std::nullptr_t' > (aka > 'nullptr_t') for 1st argument > Value(std::nullptr_t) : Type(T_Null) {} > ^ > ../include/llvm/Support/JSON.h:298:3: note: candidate template ignored: > could not match 'vector<type-parameter-0-0, > allocator<type-parameter-0-0> >' against 'llvm::json::Object' > Value(const std::vector<Elt> &C) : Value(json::Array(C)) {} > ^ > ../include/llvm/Support/JSON.h:303:3: note: candidate template ignored: > could not match 'map<std::basic_string<char>, type-parameter-0-0, > std::less<std::basic_string<char> >, allocator<pair<const > std::basic_string<char>, type-parameter-0-0> > >' against > 'llvm::json::Object' > Value(const std::map<std::string, Elt> &C) : > Value(json::Object(C)) {} > ^ > ../include/llvm/Support/JSON.h:329:42: note: candidate template > ignored: > disabled by 'enable_if' [with T = llvm::json::Object] > typename = typename std::enable_if<std::is_same<T, > bool>::value>::type, > ^ > ../include/llvm/Support/JSON.h:337:42: note: candidate template > ignored: > disabled by 'enable_if' [with T = llvm::json::Object] > typename = typename > std::enable_if<std::is_integral<T>::value>::type, > ^ > ../include/llvm/Support/JSON.h:345:41: note: candidate template > ignored: > disabled by 'enable_if' [with T = llvm::json::Object] > typename > std::enable_if<std::is_floating_point<T>::value>::type, > ^ > ../include/llvm/Support/JSON.h:355:3: note: candidate template ignored: > substitution failure [with T = llvm::json::Object]: no matching > function > for call to 'toJSON' > Value(const T &V) : Value(toJSON(V)) {} > ^ > 1 error generated. > ninja: build stopped: subcommand failed. > system(/proj/flexasic/app/ninja/1.8.2/SLED11-64/bin/ninja -j1 -C > build-all all) failed: child exited with value 1 > > > A couple of the build bots fail the same way, see e.g: > > > > http://lab.llvm.org:8011/builders/clang-cmake-armv7-quick/builds/5512/steps/build%20stage%201/logs/stdio > > > ------------- > > > This patch also causes a couple of new warnings: > > ../tools/clang/tools/extra/clangd/AST.cpp:98:13: error: unused variable > 'NS' [-Werror,-Wunused-variable] > if (auto *NS = llvm::dyn_cast<NamespaceDecl>(&ND)) > ^ > ../tools/clang/tools/extra/clangd/AST.cpp:102:13: error: unused > variable > 'En' [-Werror,-Wunused-variable] > if (auto *En = llvm::dyn_cast<EnumDecl>(&ND)) > ^ > 2 errors generated. > > /Mikael > > On 11/23/18 4:21 PM, Ilya Biryukov via cfe-commits wrote: > > Author: ibiryukov > > Date: Fri Nov 23 07:21:19 2018 > > New Revision: 347498 > > > > URL: http://llvm.org/viewvc/llvm-project?rev=347498&view=rev > > Log: > > [clangd] Add support for hierarchical documentSymbol > > > > Reviewers: ioeric, sammccall, simark > > > > Reviewed By: sammccall > > > > Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits > > > > Differential Revision: https://reviews.llvm.org/D52311 > > > > Modified: > > clang-tools-extra/trunk/clangd/AST.cpp > > clang-tools-extra/trunk/clangd/AST.h > > clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp > > clang-tools-extra/trunk/clangd/ClangdLSPServer.h > > clang-tools-extra/trunk/clangd/ClangdServer.cpp > > clang-tools-extra/trunk/clangd/ClangdServer.h > > clang-tools-extra/trunk/clangd/FindSymbols.cpp > > clang-tools-extra/trunk/clangd/FindSymbols.h > > clang-tools-extra/trunk/clangd/Protocol.cpp > > clang-tools-extra/trunk/clangd/Protocol.h > > > clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json > > clang-tools-extra/trunk/unittests/clangd/FindSymbolsTests.cpp > > clang-tools-extra/trunk/unittests/clangd/SyncAPI.cpp > > clang-tools-extra/trunk/unittests/clangd/SyncAPI.h > > > > Modified: clang-tools-extra/trunk/clangd/AST.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/AST.cpp?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/AST.cpp (original) > > +++ clang-tools-extra/trunk/clangd/AST.cpp Fri Nov 23 07:21:19 2018 > > @@ -11,9 +11,12 @@ > > > > #include "clang/AST/ASTContext.h" > > #include "clang/AST/Decl.h" > > +#include "clang/AST/DeclTemplate.h" > > #include "clang/Basic/SourceLocation.h" > > #include "clang/Basic/SourceManager.h" > > #include "clang/Index/USRGeneration.h" > > +#include "llvm/Support/Casting.h" > > +#include "llvm/Support/ScopedPrinter.h" > > > > using namespace llvm; > > namespace clang { > > @@ -61,6 +64,46 @@ std::string printQualifiedName(const Nam > > return QName; > > } > > > > +static const TemplateArgumentList * > > +getTemplateSpecializationArgs(const NamedDecl &ND) { > > + if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) > > + return Func->getTemplateSpecializationArgs(); > > + if (auto *Cls = > llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) > > + return &Cls->getTemplateInstantiationArgs(); > > + if (auto *Var = > llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) > > + return &Var->getTemplateInstantiationArgs(); > > + return nullptr; > > +} > > + > > +std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { > > + std::string Name; > > + llvm::raw_string_ostream Out(Name); > > + PrintingPolicy PP(Ctx.getLangOpts()); > > + // Handle 'using namespace'. They all have the same name - > <using-directive>. > > + if (auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) { > > + Out << "using namespace "; > > + if (auto *Qual = UD->getQualifier()) > > + Qual->print(Out, PP); > > + UD->getNominatedNamespaceAsWritten()->printName(Out); > > + return Out.str(); > > + } > > + ND.getDeclName().print(Out, PP); > > + if (!Out.str().empty()) { > > + // FIXME(ibiryukov): do not show args not explicitly written > by the user. > > + if (auto *ArgList = getTemplateSpecializationArgs(ND)) > > + printTemplateArgumentList(Out, ArgList->asArray(), PP); > > + return Out.str(); > > + } > > + // The name was empty, so present an anonymous entity. > > + if (auto *NS = llvm::dyn_cast<NamespaceDecl>(&ND)) > > + return "(anonymous namespace)"; > > + if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) > > + return ("(anonymous " + Cls->getKindName() + ")").str(); > > + if (auto *En = llvm::dyn_cast<EnumDecl>(&ND)) > > + return "(anonymous enum)"; > > + return "(anonymous)"; > > +} > > + > > std::string printNamespaceScope(const DeclContext &DC) { > > for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = > Ctx->getParent()) > > if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx)) > > > > Modified: clang-tools-extra/trunk/clangd/AST.h > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/AST.h?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/AST.h (original) > > +++ clang-tools-extra/trunk/clangd/AST.h Fri Nov 23 07:21:19 2018 > > @@ -42,6 +42,11 @@ std::string printQualifiedName(const Nam > > /// Returns the first enclosing namespace scope starting from > \p DC. > > std::string printNamespaceScope(const DeclContext &DC); > > > > +/// Prints unqualified name of the decl for the purpose of > displaying it to the > > +/// user. Anonymous decls return names of the form "(anonymous > {kind})", e.g. > > +/// "(anonymous struct)" or "(anonymous namespace)". > > +std::string printName(const ASTContext &Ctx, const NamedDecl &ND); > > + > > /// Gets the symbol ID for a declaration, if possible. > > llvm::Optional<SymbolID> getSymbolID(const Decl *D); > > > > > > Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original) > > +++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Fri Nov 23 > 07:21:19 2018 > > @@ -23,6 +23,14 @@ namespace clang { > > namespace clangd { > > namespace { > > > > +void adjustSymbolKinds(llvm::MutableArrayRef<DocumentSymbol> Syms, > > + SymbolKindBitset Kinds) { > > + for (auto &S : Syms) { > > + S.kind = adjustKindToCapability(S.kind, Kinds); > > + adjustSymbolKinds(S.children, Kinds); > > + } > > +} > > + > > SymbolKindBitset defaultSymbolKinds() { > > SymbolKindBitset Defaults; > > for (size_t I = SymbolKindMin; I <= > static_cast<size_t>(SymbolKind::Array); > > @@ -284,6 +292,8 @@ void ClangdLSPServer::onInitialize(const > > if (Params.capabilities.CompletionItemKinds) > > SupportedCompletionItemKinds |= > *Params.capabilities.CompletionItemKinds; > > SupportsCodeAction = Params.capabilities.CodeActionStructure; > > + SupportsHierarchicalDocumentSymbol = > > + Params.capabilities.HierarchicalDocumentSymbol; > > > > Reply(json::Object{ > > {{"capabilities", > > @@ -501,19 +511,48 @@ void ClangdLSPServer::onDocumentFormatti > > Reply(ReplacementsOrError.takeError()); > > } > > > > -void ClangdLSPServer::onDocumentSymbol( > > - const DocumentSymbolParams &Params, > > - Callback<std::vector<SymbolInformation>> Reply) { > > +/// The functions constructs a flattened view of the > DocumentSymbol hierarchy. > > +/// Used by the clients that do not support the hierarchical view. > > +static std::vector<SymbolInformation> > > +flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols, > > + const URIForFile &FileURI) { > > + > > + std::vector<SymbolInformation> Results; > > + std::function<void(const DocumentSymbol &, StringRef)> Process = > > + [&](const DocumentSymbol &S, Optional<StringRef> ParentName) { > > + SymbolInformation SI; > > + SI.containerName = ParentName ? "" : *ParentName; > > + SI.name = S.name; > > + SI.kind = S.kind; > > + SI.location.range = S.range; > > + SI.location.uri = FileURI; > > + > > + Results.push_back(std::move(SI)); > > + std::string FullName = > > + !ParentName ? S.name : (ParentName->str() + "::" + > S.name); > > + for (auto &C : S.children) > > + Process(C, /*ParentName=*/FullName); > > + }; > > + for (auto &S : Symbols) > > + Process(S, /*ParentName=*/""); > > + return Results; > > +} > > + > > +void ClangdLSPServer::onDocumentSymbol(const > DocumentSymbolParams &Params, > > + Callback<json::Value> > Reply) { > > + URIForFile FileURI = Params.textDocument.uri; > > Server->documentSymbols( > > Params.textDocument.uri.file(), > > Bind( > > - [this](decltype(Reply) Reply, > > - Expected<std::vector<SymbolInformation>> Items) { > > + [this, FileURI](decltype(Reply) Reply, > > + Expected<std::vector<DocumentSymbol>> > Items) { > > if (!Items) > > return Reply(Items.takeError()); > > - for (auto &Sym : *Items) > > - Sym.kind = adjustKindToCapability(Sym.kind, > SupportedSymbolKinds); > > - Reply(std::move(*Items)); > > + adjustSymbolKinds(*Items, SupportedSymbolKinds); > > + if (SupportsHierarchicalDocumentSymbol) > > + return Reply(std::move(*Items)); > > + else > > + return Reply(flattenSymbolHierarchy(*Items, FileURI)); > > }, > > std::move(Reply))); > > } > > > > Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.h > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (original) > > +++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Fri Nov 23 > 07:21:19 2018 > > @@ -66,8 +66,11 @@ private: > > Callback<std::vector<TextEdit>>); > > void onDocumentFormatting(const DocumentFormattingParams &, > > Callback<std::vector<TextEdit>>); > > + // The results are serialized 'vector<DocumentSymbol>' if > > + // SupportsHierarchicalDocumentSymbol is true and > 'vector<SymbolInformation>' > > + // otherwise. > > void onDocumentSymbol(const DocumentSymbolParams &, > > - Callback<std::vector<SymbolInformation>>); > > + Callback<llvm::json::Value>); > > void onCodeAction(const CodeActionParams &, > Callback<llvm::json::Value>); > > void onCompletion(const TextDocumentPositionParams &, > > Callback<CompletionList>); > > @@ -128,6 +131,8 @@ private: > > CompletionItemKindBitset SupportedCompletionItemKinds; > > // Whether the client supports CodeAction response objects. > > bool SupportsCodeAction = false; > > + /// From capabilities of textDocument/documentSymbol. > > + bool SupportsHierarchicalDocumentSymbol = false; > > > > // Store of the current versions of the open documents. > > DraftStore DraftMgr; > > > > Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original) > > +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Fri Nov 23 > 07:21:19 2018 > > @@ -470,10 +470,10 @@ void ClangdServer::workspaceSymbols( > > std::move(CB))); > > } > > > > -void ClangdServer::documentSymbols( > > - StringRef File, Callback<std::vector<SymbolInformation>> CB) { > > - auto Action = [](Callback<std::vector<SymbolInformation>> CB, > > - Expected<InputsAndAST> InpAST) { > > +void ClangdServer::documentSymbols(StringRef File, > > + > Callback<std::vector<DocumentSymbol>> CB) { > > + auto Action = [](Callback<std::vector<DocumentSymbol>> CB, > > + llvm::Expected<InputsAndAST> InpAST) { > > if (!InpAST) > > return CB(InpAST.takeError()); > > CB(clangd::getDocumentSymbols(InpAST->AST)); > > > > Modified: clang-tools-extra/trunk/clangd/ClangdServer.h > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/ClangdServer.h (original) > > +++ clang-tools-extra/trunk/clangd/ClangdServer.h Fri Nov 23 > 07:21:19 2018 > > @@ -167,7 +167,7 @@ public: > > > > /// Retrieve the symbols within the specified file. > > void documentSymbols(StringRef File, > > - Callback<std::vector<SymbolInformation>> CB); > > + Callback<std::vector<DocumentSymbol>> CB); > > > > /// Retrieve locations for symbol references. > > void findReferences(PathRef File, Position Pos, > > > > Modified: clang-tools-extra/trunk/clangd/FindSymbols.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/FindSymbols.cpp?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/FindSymbols.cpp (original) > > +++ clang-tools-extra/trunk/clangd/FindSymbols.cpp Fri Nov 23 > 07:21:19 2018 > > @@ -15,11 +15,13 @@ > > #include "Quality.h" > > #include "SourceCode.h" > > #include "index/Index.h" > > +#include "clang/AST/DeclTemplate.h" > > #include "clang/Index/IndexDataConsumer.h" > > #include "clang/Index/IndexSymbol.h" > > #include "clang/Index/IndexingAction.h" > > #include "llvm/Support/FormatVariadic.h" > > #include "llvm/Support/Path.h" > > +#include "llvm/Support/ScopedPrinter.h" > > > > #define DEBUG_TYPE "FindSymbols" > > > > @@ -178,104 +180,146 @@ getWorkspaceSymbols(StringRef Query, int > > } > > > > namespace { > > -/// Finds document symbols in the main file of the AST. > > -class DocumentSymbolsConsumer : public index::IndexDataConsumer { > > - ASTContext &AST; > > - std::vector<SymbolInformation> Symbols; > > - // We are always list document for the same file, so cache the > value. > > - Optional<URIForFile> MainFileUri; > > +llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const > NamedDecl &ND) { > > + auto &SM = Ctx.getSourceManager(); > > > > + SourceLocation NameLoc = findNameLoc(&ND); > > + // getFileLoc is a good choice for us, but we also need to > make sure > > + // sourceLocToPosition won't switch files, so we call > getSpellingLoc on top of > > + // that to make sure it does not switch files. > > + // FIXME: sourceLocToPosition should not switch files! > > + SourceLocation BeginLoc = > SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc())); > > + SourceLocation EndLoc = > SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc())); > > + if (NameLoc.isInvalid() || BeginLoc.isInvalid() || > EndLoc.isInvalid()) > > + return llvm::None; > > + > > + if (!SM.isWrittenInMainFile(NameLoc) || > !SM.isWrittenInMainFile(BeginLoc) || > > + !SM.isWrittenInMainFile(EndLoc)) > > + return llvm::None; > > + > > + Position NameBegin = sourceLocToPosition(SM, NameLoc); > > + Position NameEnd = sourceLocToPosition( > > + SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, > Ctx.getLangOpts())); > > + > > + index::SymbolInfo SymInfo = index::getSymbolInfo(&ND); > > + // FIXME: this is not classifying constructors, destructors > and operators > > + // correctly (they're all "methods"). > > + SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind); > > + > > + DocumentSymbol SI; > > + SI.name = printName(Ctx, ND); > > + SI.kind = SK; > > + SI.deprecated = ND.isDeprecated(); > > + SI.range = > > + Range{sourceLocToPosition(SM, BeginLoc), > sourceLocToPosition(SM, EndLoc)}; > > + SI.selectionRange = Range{NameBegin, NameEnd}; > > + if (!SI.range.contains(SI.selectionRange)) { > > + // 'selectionRange' must be contained in 'range', so in > cases where clang > > + // reports unrelated ranges we need to reconcile somehow. > > + SI.range = SI.selectionRange; > > + } > > + return SI; > > +} > > + > > +/// A helper class to build an outline for the parse AST. It > traverse the AST > > +/// directly instead of using RecursiveASTVisitor (RAV) for > three main reasons: > > +/// - there is no way to keep RAV from traversing subtrees > we're not > > +/// interested in. E.g. not traversing function locals or > implicit template > > +/// instantiations. > > +/// - it's easier to combine results of recursive passes, e.g. > > +/// - visiting decls is actually simple, so we don't hit the > complicated > > +/// cases that RAV mostly helps with (types and > expressions, etc.) > > +class DocumentOutline { > > public: > > - DocumentSymbolsConsumer(ASTContext &AST) : AST(AST) {} > > - std::vector<SymbolInformation> takeSymbols() { return > std::move(Symbols); } > > + DocumentOutline(ParsedAST &AST) : AST(AST) {} > > + > > + /// Builds the document outline for the generated AST. > > + std::vector<DocumentSymbol> build() { > > + std::vector<DocumentSymbol> Results; > > + for (auto &TopLevel : AST.getLocalTopLevelDecls()) > > + traverseDecl(TopLevel, Results); > > + return Results; > > + } > > > > - void initialize(ASTContext &Ctx) override { > > - // Compute the absolute path of the main file which we will > use for all > > - // results. > > - const SourceManager &SM = AST.getSourceManager(); > > - const FileEntry *F = SM.getFileEntryForID(SM.getMainFileID()); > > - if (!F) > > +private: > > + enum class VisitKind { No, OnlyDecl, DeclAndChildren }; > > + > > + void traverseDecl(Decl *D, std::vector<DocumentSymbol> &Results) { > > + if (auto *Templ = llvm::dyn_cast<TemplateDecl>(D)) > > + D = Templ->getTemplatedDecl(); > > + auto *ND = llvm::dyn_cast<NamedDecl>(D); > > + if (!ND) > > + return; > > + VisitKind Visit = shouldVisit(ND); > > + if (Visit == VisitKind::No) > > return; > > - auto FilePath = getRealPath(F, SM); > > - if (FilePath) > > - MainFileUri = URIForFile(*FilePath); > > + llvm::Optional<DocumentSymbol> Sym = > declToSym(AST.getASTContext(), *ND); > > + if (!Sym) > > + return; > > + if (Visit == VisitKind::DeclAndChildren) > > + traverseChildren(D, Sym->children); > > + Results.push_back(std::move(*Sym)); > > } > > > > - bool shouldIncludeSymbol(const NamedDecl *ND) { > > - if (!ND || ND->isImplicit()) > > - return false; > > - // Skip anonymous declarations, e.g (anonymous > enum/class/struct). > > - if (ND->getDeclName().isEmpty()) > > - return false; > > - return true; > > + void traverseChildren(Decl *D, std::vector<DocumentSymbol> > &Results) { > > + auto *Scope = llvm::dyn_cast<DeclContext>(D); > > + if (!Scope) > > + return; > > + for (auto *C : Scope->decls()) > > + traverseDecl(C, Results); > > } > > > > - bool > > - handleDeclOccurence(const Decl *, index::SymbolRoleSet Roles, > > - ArrayRef<index::SymbolRelation> Relations, > > - SourceLocation Loc, > > - index::IndexDataConsumer::ASTNodeInfo > ASTNode) override { > > - assert(ASTNode.OrigD); > > - // No point in continuing the index consumer if we could not > get the > > - // absolute path of the main file. > > - if (!MainFileUri) > > - return false; > > - // We only want declarations and definitions, i.e. no > references. > > - if (!(Roles & > static_cast<unsigned>(index::SymbolRole::Declaration) || > > - Roles & > static_cast<unsigned>(index::SymbolRole::Definition))) > > - return true; > > - SourceLocation NameLoc = findNameLoc(ASTNode.OrigD); > > - const SourceManager &SourceMgr = AST.getSourceManager(); > > - // We should be only be looking at "local" decls in the main > file. > > - if (!SourceMgr.isWrittenInMainFile(NameLoc)) { > > - // Even thought we are visiting only local (non-preamble) > decls, > > - // we can get here when in the presence of "extern" decls. > > - return true; > > + VisitKind shouldVisit(NamedDecl *D) { > > + if (D->isImplicit()) > > + return VisitKind::No; > > + > > + if (auto Func = llvm::dyn_cast<FunctionDecl>(D)) { > > + // Some functions are implicit template instantiations, > those should be > > + // ignored. > > + if (auto *Info = Func->getTemplateSpecializationInfo()) { > > + if (!Info->isExplicitInstantiationOrSpecialization()) > > + return VisitKind::No; > > + } > > + // Only visit the function itself, do not visit the > children (i.e. > > + // function parameters, etc.) > > + return VisitKind::OnlyDecl; > > } > > - const NamedDecl *ND = dyn_cast<NamedDecl>(ASTNode.OrigD); > > -�� if (!shouldIncludeSymbol(ND)) > > - return true; > > - > > - SourceLocation EndLoc = > > - Lexer::getLocForEndOfToken(NameLoc, 0, SourceMgr, > AST.getLangOpts()); > > - Position Begin = sourceLocToPosition(SourceMgr, NameLoc); > > - Position End = sourceLocToPosition(SourceMgr, EndLoc); > > - Range R = {Begin, End}; > > - Location L; > > - L.uri = *MainFileUri; > > - L.range = R; > > - > > - std::string QName = printQualifiedName(*ND); > > - StringRef Scope, Name; > > - std::tie(Scope, Name) = splitQualifiedName(QName); > > - Scope.consume_back("::"); > > - > > - index::SymbolInfo SymInfo = index::getSymbolInfo(ND); > > - SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind); > > - > > - SymbolInformation SI; > > - SI.name = Name; > > - SI.kind = SK; > > - SI.location = L; > > - SI.containerName = Scope; > > - Symbols.push_back(std::move(SI)); > > - return true; > > + // Handle template instantiations. We have three cases to > consider: > > + // - explicit instantiations, e.g. 'template class > std::vector<int>;' > > + // Visit the decl itself (it's present in the code), but > not the > > + // children. > > + // - implicit instantiations, i.e. not written by the user. > > + // Do not visit at all, they are not present in the code. > > + // - explicit specialization, e.g. 'template <> class > vector<bool> {};' > > + // Visit both the decl and its children, both are > written in the code. > > + if (auto *TemplSpec = > llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) { > > + if (TemplSpec->isExplicitInstantiationOrSpecialization()) > > + return TemplSpec->isExplicitSpecialization() > > + ? VisitKind::DeclAndChildren > > + : VisitKind::OnlyDecl; > > + return VisitKind::No; > > + } > > + if (auto *TemplSpec = > llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) { > > + if (TemplSpec->isExplicitInstantiationOrSpecialization()) > > + return TemplSpec->isExplicitSpecialization() > > + ? VisitKind::DeclAndChildren > > + : VisitKind::OnlyDecl; > > + return VisitKind::No; > > + } > > + // For all other cases, visit both the children and the decl. > > + return VisitKind::DeclAndChildren; > > } > > -}; > > -} // namespace > > > > -Expected<std::vector<SymbolInformation>> > getDocumentSymbols(ParsedAST &AST) { > > - DocumentSymbolsConsumer DocumentSymbolsCons(AST.getASTContext()); > > + ParsedAST &AST; > > +}; > > > > - index::IndexingOptions IndexOpts; > > - IndexOpts.SystemSymbolFilter = > > - > index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly; > > - IndexOpts.IndexFunctionLocals = false; > > - indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(), > > - AST.getLocalTopLevelDecls(), > DocumentSymbolsCons, > > - IndexOpts); > > +std::vector<DocumentSymbol> collectDocSymbols(ParsedAST &AST) { > > + return DocumentOutline(AST).build(); > > +} > > +} // namespace > > > > - return DocumentSymbolsCons.takeSymbols(); > > +llvm::Expected<std::vector<DocumentSymbol>> > getDocumentSymbols(ParsedAST &AST) { > > + return collectDocSymbols(AST); > > } > > > > } // namespace clangd > > > > Modified: clang-tools-extra/trunk/clangd/FindSymbols.h > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/FindSymbols.h?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/FindSymbols.h (original) > > +++ clang-tools-extra/trunk/clangd/FindSymbols.h Fri Nov 23 > 07:21:19 2018 > > @@ -36,8 +36,7 @@ getWorkspaceSymbols(llvm::StringRef Quer > > > > /// Retrieves the symbols contained in the "main file" section > of an AST in the > > /// same order that they appear. > > -llvm::Expected<std::vector<SymbolInformation>> > > -getDocumentSymbols(ParsedAST &AST); > > +llvm::Expected<std::vector<DocumentSymbol>> > getDocumentSymbols(ParsedAST &AST); > > > > } // namespace clangd > > } // namespace clang > > > > Modified: clang-tools-extra/trunk/clangd/Protocol.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/Protocol.cpp (original) > > +++ clang-tools-extra/trunk/clangd/Protocol.cpp Fri Nov 23 > 07:21:19 2018 > > @@ -18,6 +18,7 @@ > > #include "llvm/ADT/SmallString.h" > > #include "llvm/Support/Format.h" > > #include "llvm/Support/FormatVariadic.h" > > +#include "llvm/Support/JSON.h" > > #include "llvm/Support/Path.h" > > #include "llvm/Support/raw_ostream.h" > > > > @@ -222,6 +223,11 @@ bool fromJSON(const json::Value &Params, > > if (CodeAction->getObject("codeActionLiteralSupport")) > > R.CodeActionStructure = true; > > } > > + if (auto *DocumentSymbol = > TextDocument->getObject("documentSymbol")) { > > + if (auto HierarchicalSupport = > > + > DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport")) > > + R.HierarchicalDocumentSymbol = *HierarchicalSupport; > > + } > > } > > if (auto *Workspace = O->getObject("workspace")) { > > if (auto *Symbol = Workspace->getObject("symbol")) { > > @@ -449,6 +455,25 @@ json::Value toJSON(const CodeAction &CA) > > return std::move(CodeAction); > > } > > > > +llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const > DocumentSymbol &S) { > > + return O << S.name << " - " << toJSON(S); > > +} > > + > > +llvm::json::Value toJSON(const DocumentSymbol &S) { > > + json::Object Result{{"name", S.name}, > > + {"kind", static_cast<int>(S.kind)}, > > + {"range", S.range}, > > + {"selectionRange", S.selectionRange}}; > > + > > + if (!S.detail.empty()) > > + Result["detail"] = S.detail; > > + if (!S.children.empty()) > > + Result["children"] = S.children; > > + if (S.deprecated) > > + Result["deprecated"] = true; > > + return Result; > > +} > > + > > json::Value toJSON(const WorkspaceEdit &WE) { > > if (!WE.changes) > > return json::Object{}; > > > > Modified: clang-tools-extra/trunk/clangd/Protocol.h > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/clangd/Protocol.h (original) > > +++ clang-tools-extra/trunk/clangd/Protocol.h Fri Nov 23 07:21:19 > 2018 > > @@ -150,6 +150,9 @@ struct Range { > > } > > > > bool contains(Position Pos) const { return start <= Pos && > Pos < end; } > > + bool contains(Range Rng) const { > > + return start <= Rng.start && Rng.end <= end; > > + } > > }; > > bool fromJSON(const llvm::json::Value &, Range &); > > llvm::json::Value toJSON(const Range &); > > @@ -331,6 +334,9 @@ struct ClientCapabilities { > > /// textDocument.completion.completionItem.snippetSupport > > bool CompletionSnippets = false; > > > > + /// Client supports hierarchical document symbols. > > + bool HierarchicalDocumentSymbol = false; > > + > > /// The supported set of CompletionItemKinds for > textDocument/completion. > > /// textDocument.completion.completionItemKind.valueSet > > llvm::Optional<CompletionItemKindBitset> CompletionItemKinds; > > @@ -655,6 +661,39 @@ struct CodeAction { > > }; > > llvm::json::Value toJSON(const CodeAction &); > > > > +/// Represents programming constructs like variables, classes, > interfaces etc. > > +/// that appear in a document. Document symbols can be > hierarchical and they > > +/// have two ranges: one that encloses its definition and one > that points to its > > +/// most interesting range, e.g. the range of an identifier. > > +struct DocumentSymbol { > > + /// The name of this symbol. > > + std::string name; > > + > > + /// More detail for this symbol, e.g the signature of a function. > > + std::string detail; > > + > > + /// The kind of this symbol. > > + SymbolKind kind; > > + > > + /// Indicates if this symbol is deprecated. > > + bool deprecated; > > + > > + /// The range enclosing this symbol not including > leading/trailing whitespace > > + /// but everything else like comments. This information is > typically used to > > + /// determine if the clients cursor is inside the symbol to > reveal in the > > + /// symbol in the UI. > > + Range range; > > + > > + /// The range that should be selected and revealed when this > symbol is being > > + /// picked, e.g the name of a function. Must be contained by > the `range`. > > + Range selectionRange; > > + > > + /// Children of this symbol, e.g. properties of a class. > > + std::vector<DocumentSymbol> children; > > +}; > > +llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const > DocumentSymbol &S); > > +llvm::json::Value toJSON(const DocumentSymbol &S); > > + > > /// Represents information about programming constructs like > variables, classes, > > /// interfaces etc. > > struct SymbolInformation { > > > > Modified: > clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- > clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json > (original) > > +++ > clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json > Fri Nov 23 07:21:19 2018 > > @@ -6,7 +6,7 @@ > > "publisher": "llvm-vs-code-extensions", > > "homepage": "https://clang.llvm.org/extra/clangd.html", > > "engines": { > > - "vscode": "^1.18.0" > > + "vscode": "^1.27.0" > > }, > > "categories": [ > > "Programming Languages", > > @@ -32,8 +32,8 @@ > > "test": "node ./node_modules/vscode/bin/test" > > }, > > "dependencies": { > > - "vscode-languageclient": "^4.0.0", > > - "vscode-languageserver": "^4.0.0" > > + "vscode-languageclient": "^5.1.0", > > + "vscode-languageserver": "^5.1.0" > > }, > > "devDependencies": { > > "typescript": "^2.0.3", > > > > Modified: > clang-tools-extra/trunk/unittests/clangd/FindSymbolsTests.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/FindSymbolsTests.cpp?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/unittests/clangd/FindSymbolsTests.cpp > (original) > > +++ clang-tools-extra/trunk/unittests/clangd/FindSymbolsTests.cpp > Fri Nov 23 07:21:19 2018 > > @@ -14,6 +14,8 @@ > > #include "gmock/gmock.h" > > #include "gtest/gtest.h" > > > > +using namespace llvm; > > + > > namespace clang { > > namespace clangd { > > > > @@ -23,6 +25,7 @@ using ::testing::AllOf; > > using ::testing::AnyOf; > > using ::testing::ElementsAre; > > using ::testing::ElementsAreArray; > > +using ::testing::Field; > > using ::testing::IsEmpty; > > using ::testing::UnorderedElementsAre; > > > > @@ -37,9 +40,17 @@ MATCHER_P(QName, Name, "") { > > return arg.name <http://arg.name> == Name; > > return (arg.containerName + "::" + arg.name > <http://arg.name>) == Name; > > } > > +MATCHER_P(WithName, N, "") { return arg.name <http://arg.name> > == N; } > > MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; } > > MATCHER_P(SymRange, Range, "") { return arg.location.range == > Range; } > > > > +// GMock helpers for matching DocumentSymbol. > > +MATCHER_P(SymNameRange, Range, "") { return arg.selectionRange > == Range; } > > +template <class... ChildMatchers> > > +testing::Matcher<DocumentSymbol> Children(ChildMatchers... > ChildrenM) { > > + return Field(&DocumentSymbol::children, > ElementsAre(ChildrenM...)); > > +} > > + > > ClangdServer::Options optsForTests() { > > auto ServerOpts = ClangdServer::optsForTest(); > > ServerOpts.WorkspaceRoot = testRoot(); > > @@ -300,7 +311,7 @@ protected: > > IgnoreDiagnostics DiagConsumer; > > ClangdServer Server; > > > > - std::vector<SymbolInformation> getSymbols(PathRef File) { > > + std::vector<DocumentSymbol> getSymbols(PathRef File) { > > EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for > preamble"; > > auto SymbolInfos = runDocumentSymbols(Server, File); > > EXPECT_TRUE(bool(SymbolInfos)) << "documentSymbols returned > an error"; > > @@ -363,31 +374,46 @@ TEST_F(DocumentSymbolsTest, BasicSymbols > > )"); > > > > addFile(FilePath, Main.code()); > > - EXPECT_THAT(getSymbols(FilePath), > > - ElementsAreArray( > > - {AllOf(QName("Foo"), WithKind(SymbolKind::Class)), > > - AllOf(QName("Foo"), WithKind(SymbolKind::Class)), > > - AllOf(QName("Foo::Foo"), > WithKind(SymbolKind::Method)), > > - AllOf(QName("Foo::Foo"), > WithKind(SymbolKind::Method)), > > - AllOf(QName("Foo::f"), > WithKind(SymbolKind::Method)), > > - AllOf(QName("f1"), > WithKind(SymbolKind::Function)), > > - AllOf(QName("Foo::operator="), > WithKind(SymbolKind::Method)), > > - AllOf(QName("Foo::~Foo"), > WithKind(SymbolKind::Method)), > > - AllOf(QName("Foo::Nested"), > WithKind(SymbolKind::Class)), > > - AllOf(QName("Foo::Nested::f"), > WithKind(SymbolKind::Method)), > > - AllOf(QName("Friend"), > WithKind(SymbolKind::Class)), > > - AllOf(QName("f1"), > WithKind(SymbolKind::Function)), > > - AllOf(QName("f2"), > WithKind(SymbolKind::Function)), > > - AllOf(QName("KInt"), > WithKind(SymbolKind::Variable)), > > - AllOf(QName("kStr"), > WithKind(SymbolKind::Variable)), > > - AllOf(QName("f1"), > WithKind(SymbolKind::Function)), > > - AllOf(QName("foo"), > WithKind(SymbolKind::Namespace)), > > - AllOf(QName("foo::int32"), > WithKind(SymbolKind::Class)), > > - AllOf(QName("foo::int32_t"), > WithKind(SymbolKind::Class)), > > - AllOf(QName("foo::v1"), > WithKind(SymbolKind::Variable)), > > - AllOf(QName("foo::bar"), > WithKind(SymbolKind::Namespace)), > > - AllOf(QName("foo::bar::v2"), > WithKind(SymbolKind::Variable)), > > - AllOf(QName("foo::baz"), > WithKind(SymbolKind::Namespace))})); > > + EXPECT_THAT( > > + getSymbols(FilePath), > > + ElementsAreArray( > > + {AllOf(WithName("Foo"), WithKind(SymbolKind::Class), > Children()), > > + AllOf(WithName("Foo"), WithKind(SymbolKind::Class), > > + Children(AllOf(WithName("Foo"), > WithKind(SymbolKind::Method), > > + Children()), > > + AllOf(WithName("Foo"), > WithKind(SymbolKind::Method), > > + Children()), > > + AllOf(WithName("f"), > WithKind(SymbolKind::Method), > > + Children()), > > + AllOf(WithName("operator="), > > + WithKind(SymbolKind::Method), > Children()), > > + AllOf(WithName("~Foo"), > WithKind(SymbolKind::Method), > > + Children()), > > + AllOf(WithName("Nested"), > WithKind(SymbolKind::Class), > > + Children(AllOf(WithName("f"), > > + > WithKind(SymbolKind::Method), > > + Children()))))), > > + AllOf(WithName("Friend"), > WithKind(SymbolKind::Class), Children()), > > + AllOf(WithName("f1"), WithKind(SymbolKind::Function), > Children()), > > + AllOf(WithName("f2"), WithKind(SymbolKind::Function), > Children()), > > + AllOf(WithName("KInt"), > WithKind(SymbolKind::Variable), Children()), > > + AllOf(WithName("kStr"), > WithKind(SymbolKind::Variable), Children()), > > + AllOf(WithName("f1"), WithKind(SymbolKind::Function), > Children()), > > + AllOf(WithName("foo"), WithKind(SymbolKind::Namespace), > > + Children( > > + AllOf(WithName("int32"), > WithKind(SymbolKind::Class), > > + Children()), > > + AllOf(WithName("int32_t"), > WithKind(SymbolKind::Class), > > + Children()), > > + AllOf(WithName("v1"), > WithKind(SymbolKind::Variable), > > + Children()), > > + AllOf(WithName("bar"), > WithKind(SymbolKind::Namespace), > > + Children(AllOf(WithName("v2"), > > + > WithKind(SymbolKind::Variable), > > + Children()))), > > + AllOf(WithName("baz"), > WithKind(SymbolKind::Namespace), > > + Children()), > > + AllOf(WithName("v2"), > WithKind(SymbolKind::Variable))))})); > > } > > > > TEST_F(DocumentSymbolsTest, DeclarationDefinition) { > > @@ -402,11 +428,12 @@ TEST_F(DocumentSymbolsTest, DeclarationD > > > > addFile(FilePath, Main.code()); > > EXPECT_THAT(getSymbols(FilePath), > > - ElementsAre(AllOf(QName("Foo"), > WithKind(SymbolKind::Class)), > > - AllOf(QName("Foo::f"), > WithKind(SymbolKind::Method), > > - SymRange(Main.range("decl"))), > > - AllOf(QName("Foo::f"), > WithKind(SymbolKind::Method), > > - SymRange(Main.range("def"))))); > > + ElementsAre(AllOf(WithName("Foo"), > WithKind(SymbolKind::Class), > > + Children(AllOf( > > + WithName("f"), > WithKind(SymbolKind::Method), > > + > SymNameRange(Main.range("decl"))))), > > + AllOf(WithName("f"), > WithKind(SymbolKind::Method), > > + SymNameRange(Main.range("def"))))); > > } > > > > TEST_F(DocumentSymbolsTest, ExternSymbol) { > > @@ -429,7 +456,7 @@ TEST_F(DocumentSymbolsTest, NoLocals) { > > struct LocalClass {}; > > int local_var; > > })cpp"); > > - EXPECT_THAT(getSymbols(FilePath), ElementsAre(QName("test"))); > > + EXPECT_THAT(getSymbols(FilePath), ElementsAre(WithName("test"))); > > } > > > > TEST_F(DocumentSymbolsTest, Unnamed) { > > @@ -442,9 +469,12 @@ TEST_F(DocumentSymbolsTest, Unnamed) { > > )cpp"); > > EXPECT_THAT( > > getSymbols(FilePath), > > - ElementsAre(AllOf(QName("UnnamedStruct"), > WithKind(SymbolKind::Variable)), > > - AllOf(QName("(anonymous struct)::InUnnamed"), > > - WithKind(SymbolKind::Field)))); > > + ElementsAre( > > + AllOf(WithName("(anonymous struct)"), > WithKind(SymbolKind::Struct), > > + Children(AllOf(WithName("InUnnamed"), > > + WithKind(SymbolKind::Field), > Children()))), > > + AllOf(WithName("UnnamedStruct"), > WithKind(SymbolKind::Variable), > > + Children()))); > > } > > > > TEST_F(DocumentSymbolsTest, InHeaderFile) { > > @@ -461,23 +491,46 @@ TEST_F(DocumentSymbolsTest, InHeaderFile > > addFile("foo.cpp", R"cpp( > > #include "foo.h" > > )cpp"); > > - EXPECT_THAT(getSymbols(FilePath), ElementsAre(QName("test"))); > > + EXPECT_THAT(getSymbols(FilePath), ElementsAre(WithName("test"))); > > } > > > > TEST_F(DocumentSymbolsTest, Template) { > > std::string FilePath = testPath("foo.cpp"); > > addFile(FilePath, R"( > > - // Primary templates and specializations are included but > instantiations > > - // are not. > > template <class T> struct Tmpl {T x = 0;}; > > - template <> struct Tmpl<int> {}; > > + template <> struct Tmpl<int> { > > + int y = 0; > > + }; > > extern template struct Tmpl<float>; > > template struct Tmpl<double>; > > + > > + template <class T, class U, class Z = float> > > + int funcTmpl(U a); > > + template <> > > + int funcTmpl<int>(double a); > > + > > + template <class T, class U = double> > > + int varTmpl = T(); > > + template <> > > + double varTmpl<int> = 10.0; > > )"); > > - EXPECT_THAT(getSymbols(FilePath), > > - ElementsAre(AllOf(QName("Tmpl"), > WithKind(SymbolKind::Struct)), > > - AllOf(QName("Tmpl::x"), > WithKind(SymbolKind::Field)), > > - AllOf(QName("Tmpl"), > WithKind(SymbolKind::Struct)))); > > + EXPECT_THAT( > > + getSymbols(FilePath), > > + ElementsAre( > > + AllOf(WithName("Tmpl"), WithKind(SymbolKind::Struct), > > + Children(AllOf(WithName("x"), > WithKind(SymbolKind::Field)))), > > + AllOf(WithName("Tmpl<int>"), WithKind(SymbolKind::Struct), > > + Children(WithName("y"))), > > + AllOf(WithName("Tmpl<float>"), > WithKind(SymbolKind::Struct), > > + Children()), > > + AllOf(WithName("Tmpl<double>"), > WithKind(SymbolKind::Struct), > > + Children()), > > + AllOf(WithName("funcTmpl"), Children()), > > + // FIXME(ibiryukov): template args should be <int> to > match the code. > > + AllOf(WithName("funcTmpl<int, double, float>"), > Children()), > > + AllOf(WithName("varTmpl"), Children()), > > + // FIXME(ibiryukov): template args should be <int> to > match the code. > > + AllOf(WithName("varTmpl<int, double>"), Children()))); > > } > > > > TEST_F(DocumentSymbolsTest, Namespaces) { > > @@ -507,10 +560,15 @@ TEST_F(DocumentSymbolsTest, Namespaces) > > )cpp"); > > EXPECT_THAT( > > getSymbols(FilePath), > > - ElementsAreArray({QName("ans1"), QName("ans1::ai1"), > QName("ans1::ans2"), > > - QName("ans1::ans2::ai2"), QName("test"), > QName("na"), > > - QName("na::nb"), QName("na::Foo"), > QName("na"), > > - QName("na::nb"), QName("na::Bar")})); > > + ElementsAreArray<testing::Matcher<DocumentSymbol>>( > > + {AllOf(WithName("ans1"), > > + Children(AllOf(WithName("ai1"), Children()), > > + AllOf(WithName("ans2"), > Children(WithName("ai2"))))), > > + AllOf(WithName("(anonymous namespace)"), > Children(WithName("test"))), > > + AllOf(WithName("na"), > > + Children(AllOf(WithName("nb"), > Children(WithName("Foo"))))), > > + AllOf(WithName("na"), > > + Children(AllOf(WithName("nb"), > Children(WithName("Bar")))))})); > > } > > > > TEST_F(DocumentSymbolsTest, Enums) { > > @@ -531,10 +589,14 @@ TEST_F(DocumentSymbolsTest, Enums) { > > }; > > } > > )"); > > - EXPECT_THAT(getSymbols(FilePath), > > - ElementsAre(QName("Red"), QName("Color"), > QName("Green"), > > - QName("Color2"), > QName("Color2::Yellow"), QName("ns"), > > - QName("ns::Black"))); > > + EXPECT_THAT( > > + getSymbols(FilePath), > > + ElementsAre( > > + AllOf(WithName("(anonymous enum)"), > Children(WithName("Red"))), > > + AllOf(WithName("Color"), Children(WithName("Green"))), > > + AllOf(WithName("Color2"), Children(WithName("Yellow"))), > > + AllOf(WithName("ns"), > Children(AllOf(WithName("(anonymous enum)"), > > + > Children(WithName("Black"))))))); > > } > > > > TEST_F(DocumentSymbolsTest, FromMacro) { > > @@ -553,8 +615,43 @@ TEST_F(DocumentSymbolsTest, FromMacro) { > > addFile(FilePath, Main.code()); > > EXPECT_THAT( > > getSymbols(FilePath), > > - ElementsAre(AllOf(QName("abc_Test"), > SymRange(Main.range("expansion"))), > > - AllOf(QName("Test"), > SymRange(Main.range("spelling"))))); > > + ElementsAre( > > + AllOf(WithName("abc_Test"), > SymNameRange(Main.range("expansion"))), > > + AllOf(WithName("Test"), > SymNameRange(Main.range("spelling"))))); > > +} > > + > > +TEST_F(DocumentSymbolsTest, FuncTemplates) { > > + std::string FilePath = testPath("foo.cpp"); > > + Annotations Source(R"cpp( > > + template <class T> > > + T foo() {} > > + > > + auto x = foo<int>(); > > + auto y = foo<double>() > > + )cpp"); > > + addFile(FilePath, Source.code()); > > + // Make sure we only see the template declaration, not > instantiations. > > + EXPECT_THAT(getSymbols(FilePath), > > + ElementsAre(WithName("foo"), WithName("x"), > WithName("y"))); > > +} > > + > > +TEST_F(DocumentSymbolsTest, UsingDirectives) { > > + std::string FilePath = testPath("foo.cpp"); > > + Annotations Source(R"cpp( > > + namespace ns { > > + int foo; > > + } > > + > > + namespace ns_alias = ns; > > + > > + using namespace ::ns; // check we don't loose qualifiers. > > + using namespace ns_alias; // and namespace aliases. > > + )cpp"); > > + addFile(FilePath, Source.code()); > > + EXPECT_THAT(getSymbols(FilePath), > > + ElementsAre(WithName("ns"), WithName("ns_alias"), > > + WithName("using namespace ::ns"), > > + WithName("using namespace ns_alias"))); > > } > > > > } // namespace clangd > > > > Modified: clang-tools-extra/trunk/unittests/clangd/SyncAPI.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/SyncAPI.cpp?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/unittests/clangd/SyncAPI.cpp (original) > > +++ clang-tools-extra/trunk/unittests/clangd/SyncAPI.cpp Fri Nov > 23 07:21:19 2018 > > @@ -120,9 +120,9 @@ runWorkspaceSymbols(ClangdServer &Server > > return std::move(*Result); > > } > > > > -Expected<std::vector<SymbolInformation>> > > -runDocumentSymbols(ClangdServer &Server, PathRef File) { > > - Optional<Expected<std::vector<SymbolInformation>>> Result; > > +Expected<std::vector<DocumentSymbol>> > runDocumentSymbols(ClangdServer &Server, > > + PathRef > File) { > > + Optional<Expected<std::vector<DocumentSymbol>>> Result; > > Server.documentSymbols(File, capture(Result)); > > return std::move(*Result); > > } > > > > Modified: clang-tools-extra/trunk/unittests/clangd/SyncAPI.h > > URL: > > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/SyncAPI.h?rev=347498&r1=347497&r2=347498&view=diff > > > > ============================================================================== > > --- clang-tools-extra/trunk/unittests/clangd/SyncAPI.h (original) > > +++ clang-tools-extra/trunk/unittests/clangd/SyncAPI.h Fri Nov 23 > 07:21:19 2018 > > @@ -47,8 +47,8 @@ std::string runDumpAST(ClangdServer &Ser > > llvm::Expected<std::vector<SymbolInformation>> > > runWorkspaceSymbols(ClangdServer &Server, StringRef Query, int > Limit); > > > > -llvm::Expected<std::vector<SymbolInformation>> > > -runDocumentSymbols(ClangdServer &Server, PathRef File); > > +Expected<std::vector<DocumentSymbol>> > runDocumentSymbols(ClangdServer &Server, > > + PathRef > File); > > > > SymbolSlab runFuzzyFind(const SymbolIndex &Index, StringRef Query); > > SymbolSlab runFuzzyFind(const SymbolIndex &Index, const > FuzzyFindRequest &Req); > > > > > > _______________________________________________ > > cfe-commits mailing list > > cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org> > > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > > > > > > -- > Regards, > Ilya Biryukov _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits