[clang-tools-extra] r347498 - [clangd] Add support for hierarchical documentSymbol
Ilya Biryukov via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 26 03:41:50 PST 2018
Sorry about that, should be fixed in r347539.
On Mon, Nov 26, 2018 at 8:10 AM Mikael Holmén <mikael.holmen at 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 == Name;
> > return (arg.containerName + "::" + arg.name) == Name;
> > }
> > +MATCHER_P(WithName, N, "") { return 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 at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> >
>
--
Regards,
Ilya Biryukov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181126/922f3ee6/attachment-0001.html>
More information about the cfe-commits
mailing list