diff --git a/.arclint b/.arclint index 01de1ee897adaa14b29279f47b7d5ddcde5b52e3..246ff9f39d475774ed37d87f89ac2be6e2820714 100644 --- a/.arclint +++ b/.arclint @@ -2,7 +2,7 @@ "linters": { "clang-format": { "type": "script-and-regex", - "script-and-regex.script": "utils/arcanist/clang-format.sh", + "script-and-regex.script": "bash utils/arcanist/clang-format.sh", "script-and-regex.regex": "/^(?P[[:alpha:]]+)\n(?P[^\n]+)\n(====|(?P\\d),(?P\\d)\n(?P.*)>>>>\n(?P.*)<<<<\n)$/s", "include": [ "(\\.(cc|cpp|h)$)" diff --git a/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp b/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp index b58288500dcf64abaea98735f792240e53280231..0e537fc3cc4eb1a194b896b89f1c944729e51eb8 100644 --- a/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp @@ -23,19 +23,14 @@ namespace abseil { // `FactoryName`, return `None`. static llvm::Optional getScaleForFactory(llvm::StringRef FactoryName) { - static const std::unordered_map ScaleMap( - {{"Nanoseconds", DurationScale::Nanoseconds}, - {"Microseconds", DurationScale::Microseconds}, - {"Milliseconds", DurationScale::Milliseconds}, - {"Seconds", DurationScale::Seconds}, - {"Minutes", DurationScale::Minutes}, - {"Hours", DurationScale::Hours}}); - - auto ScaleIter = ScaleMap.find(std::string(FactoryName)); - if (ScaleIter == ScaleMap.end()) - return llvm::None; - - return ScaleIter->second; + return llvm::StringSwitch>(FactoryName) + .Case("Nanoseconds", DurationScale::Nanoseconds) + .Case("Microseconds", DurationScale::Microseconds) + .Case("Milliseconds", DurationScale::Milliseconds) + .Case("Seconds", DurationScale::Seconds) + .Case("Minutes", DurationScale::Minutes) + .Case("Hours", DurationScale::Hours) + .Default(llvm::None); } // Given either an integer or float literal, return its value. diff --git a/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt index d7965e126b7228631a109eb6bade8b47989b2f67..9d4edb2abf1a245b33d17914d555a1cbd01f5a74 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ) add_clang_library(clangTidyLLVMLibcModule + CalleeNamespaceCheck.cpp ImplementationInNamespaceCheck.cpp LLVMLibcTidyModule.cpp RestrictSystemLibcHeadersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbc6762a44e78ea4c48956658bcbbd0295dbd063 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp @@ -0,0 +1,56 @@ +//===-- CalleeNamespaceCheck.cpp ------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CalleeNamespaceCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace llvm_libc { + +// Gets the outermost namespace of a DeclContext, right under the Translation +// Unit. +const DeclContext *getOutermostNamespace(const DeclContext *Decl) { + const DeclContext *Parent = Decl->getParent(); + if (Parent && Parent->isTranslationUnit()) + return Decl; + return getOutermostNamespace(Parent); +} + +void CalleeNamespaceCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + declRefExpr(to(functionDecl().bind("func"))).bind("use-site"), this); +} + +void CalleeNamespaceCheck::check(const MatchFinder::MatchResult &Result) { + const auto *UsageSiteExpr = Result.Nodes.getNodeAs("use-site"); + const auto *FuncDecl = Result.Nodes.getNodeAs("func"); + + // Ignore compiler builtin functions. + if (FuncDecl->getBuiltinID() != 0) + return; + + // If the outermost namespace of the function is __llvm_libc, we're good. + const auto *NS = dyn_cast(getOutermostNamespace(FuncDecl)); + if (NS && NS->getName() == "__llvm_libc") + return; + + diag(UsageSiteExpr->getBeginLoc(), "%0 must resolve to a function declared " + "within the '__llvm_libc' namespace") + << FuncDecl; + + diag(FuncDecl->getLocation(), "resolves to this declaration", + clang::DiagnosticIDs::Note); +} + +} // namespace llvm_libc +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.h b/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..b35c6011f088945b19f18d614d0a4e61c4be22fd --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.h @@ -0,0 +1,38 @@ +//===-- CalleeNamespaceCheck.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_CALLEENAMESPACECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_CALLEENAMESPACECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace llvm_libc { + +/// Checks all calls resolve to functions within __llvm_libc namespace. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/llvmlibc-callee-namespace.html +class CalleeNamespaceCheck : public ClangTidyCheck { +public: + CalleeNamespaceCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace llvm_libc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_CALLEENAMESPACECHECK_H diff --git a/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp b/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp index 8c5a7ac2016163bacf9a97a9c975191a1db9c12c..61cfe29536646ed07ebd6673f1874cad2b3bbae9 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp @@ -9,6 +9,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "CalleeNamespaceCheck.h" #include "ImplementationInNamespaceCheck.h" #include "RestrictSystemLibcHeadersCheck.h" @@ -19,6 +20,8 @@ namespace llvm_libc { class LLVMLibcModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "llvmlibc-callee-namespace"); CheckFactories.registerCheck( "llvmlibc-implementation-in-namespace"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp index 15eb2e88285c4adede812958d93fe61f3c1ea189..2eef9837e11c17c41878026b918dd588b49ddb3f 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp @@ -21,10 +21,13 @@ static constexpr std::array DeprecatedTypes = { "::std::ios_base::seek_dir", "::std::ios_base::streamoff", "::std::ios_base::streampos"}; -static const llvm::StringMap ReplacementTypes = { - {"io_state", "iostate"}, - {"open_mode", "openmode"}, - {"seek_dir", "seekdir"}}; +static llvm::Optional getReplacementType(StringRef Type) { + return llvm::StringSwitch>(Type) + .Case("io_state", "iostate") + .Case("open_mode", "openmode") + .Case("seek_dir", "seekdir") + .Default(llvm::None); +} void DeprecatedIosBaseAliasesCheck::registerMatchers(MatchFinder *Finder) { auto IoStateDecl = typedefDecl(hasAnyName(DeprecatedTypes)).bind("TypeDecl"); @@ -40,14 +43,14 @@ void DeprecatedIosBaseAliasesCheck::check( const auto *Typedef = Result.Nodes.getNodeAs("TypeDecl"); StringRef TypeName = Typedef->getName(); - bool HasReplacement = ReplacementTypes.count(TypeName); + auto Replacement = getReplacementType(TypeName); const auto *TL = Result.Nodes.getNodeAs("TypeLoc"); SourceLocation IoStateLoc = TL->getBeginLoc(); // Do not generate fixits for matches depending on template arguments and // macro expansions. - bool Fix = HasReplacement && !TL->getType()->isDependentType(); + bool Fix = Replacement && !TL->getType()->isDependentType(); if (IoStateLoc.isMacroID()) { IoStateLoc = SM.getSpellingLoc(IoStateLoc); Fix = false; @@ -55,8 +58,8 @@ void DeprecatedIosBaseAliasesCheck::check( SourceLocation EndLoc = IoStateLoc.getLocWithOffset(TypeName.size() - 1); - if (HasReplacement) { - auto FixName = ReplacementTypes.lookup(TypeName); + if (Replacement) { + auto FixName = *Replacement; auto Builder = diag(IoStateLoc, "'std::ios_base::%0' is deprecated; use " "'std::ios_base::%1' instead") << TypeName << FixName; diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index ee6234704ff5f3d2ddaf444116a292e2ab43c681..011da5e8840d8a18ae615d7a3cffba59612bc67d 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -525,13 +525,11 @@ void LoopConvertCheck::doConversion( const ValueDecl *MaybeContainer, const UsageResult &Usages, const DeclStmt *AliasDecl, bool AliasUseRequired, bool AliasFromForInit, const ForStmt *Loop, RangeDescriptor Descriptor) { - auto Diag = diag(Loop->getForLoc(), "use range-based for loop instead"); - std::string VarName; bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl; bool AliasVarIsRef = false; bool CanCopy = true; - + std::vector FixIts; if (VarNameFromAlias) { const auto *AliasVar = cast(AliasDecl->getSingleDecl()); VarName = AliasVar->getName().str(); @@ -563,8 +561,8 @@ void LoopConvertCheck::doConversion( getAliasRange(Context->getSourceManager(), ReplaceRange); } - Diag << FixItHint::CreateReplacement( - CharSourceRange::getTokenRange(ReplaceRange), ReplacementText); + FixIts.push_back(FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(ReplaceRange), ReplacementText)); // No further replacements are made to the loop, since the iterator or index // was used exactly once - in the initialization of AliasVar. } else { @@ -609,8 +607,8 @@ void LoopConvertCheck::doConversion( Usage.Kind == Usage::UK_CaptureByCopy ? "&" + VarName : VarName; } TUInfo->getReplacedVars().insert(std::make_pair(Loop, IndexVar)); - Diag << FixItHint::CreateReplacement( - CharSourceRange::getTokenRange(Range), ReplaceText); + FixIts.push_back(FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(Range), ReplaceText)); } } @@ -648,8 +646,9 @@ void LoopConvertCheck::doConversion( std::string Range = ("(" + TypeString + " " + VarName + " : " + MaybeDereference + Descriptor.ContainerString + ")") .str(); - Diag << FixItHint::CreateReplacement( - CharSourceRange::getTokenRange(ParenRange), Range); + FixIts.push_back(FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(ParenRange), Range)); + diag(Loop->getForLoc(), "use range-based for loop instead") << FixIts; TUInfo->getGeneratedDecls().insert(make_pair(Loop, VarName)); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp index f352374d4b9100e81ba6a02dc06d813fea4e0016..f6dc5c044a7adcfd2ac615f2e9b0009d50bbaac4 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp @@ -58,6 +58,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) { printPolicy.SuppressScope = true; printPolicy.ConstantArraySizeAsWritten = true; printPolicy.UseVoidForZeroParams = false; + printPolicy.PrintInjectedClassNameWithArguments = false; std::string Type = MatchedDecl->getUnderlyingType().getAsString(printPolicy); std::string Name = MatchedDecl->getNameAsString(); diff --git a/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp b/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp index d567f524a6d113634b8f032793ff817f293f62a7..db9cc8c5a08c004cbb8eaa0bec74414d6d48b0de 100644 --- a/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp +++ b/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp @@ -43,21 +43,15 @@ static StringRef TrySuggestPPC(StringRef Name) { if (!Name.consume_front("vec_")) return {}; - static const llvm::StringMap Mapping{ - // [simd.alg] - {"max", "$std::max"}, - {"min", "$std::min"}, - - // [simd.binary] - {"add", "operator+ on $simd objects"}, - {"sub", "operator- on $simd objects"}, - {"mul", "operator* on $simd objects"}, - }; - - auto It = Mapping.find(Name); - if (It != Mapping.end()) - return It->second; - return {}; + return llvm::StringSwitch(Name) + // [simd.alg] + .Case("max", "$std::max") + .Case("min", "$std::min") + // [simd.binary] + .Case("add", "operator+ on $simd objects") + .Case("sub", "operator- on $simd objects") + .Case("mul", "operator* on $simd objects") + .Default({}); } static StringRef TrySuggestX86(StringRef Name) { diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py index 1eb13529575485c0f823669b7e7070d07db45d48..1c4f3ad59ac813bfbd3de8ba0e24db1f4e5c8493 100755 --- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py +++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py @@ -78,10 +78,12 @@ def make_absolute(f, directory): def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path, - header_filter, extra_arg, extra_arg_before, quiet, - config): + header_filter, allow_enabling_alpha_checkers, + extra_arg, extra_arg_before, quiet, config): """Gets a command line for clang-tidy.""" start = [clang_tidy_binary] + if allow_enabling_alpha_checkers is not None: + start.append('-allow-enabling-analyzer-alpha-checkers') if header_filter is not None: start.append('-header-filter=' + header_filter) if checks: @@ -159,6 +161,7 @@ def run_tidy(args, tmpdir, build_path, queue, lock, failed_files): name = queue.get() invocation = get_tidy_invocation(name, args.clang_tidy_binary, args.checks, tmpdir, build_path, args.header_filter, + args.allow_enabling_alpha_checkers, args.extra_arg, args.extra_arg_before, args.quiet, args.config) @@ -179,6 +182,9 @@ def main(): 'in a compilation database. Requires ' 'clang-tidy and clang-apply-replacements in ' '$PATH.') + parser.add_argument('-allow-enabling-alpha-checkers', + action='store_true', help='allow alpha checkers from ' + 'clang-analyzer.') parser.add_argument('-clang-tidy-binary', metavar='PATH', default='clang-tidy', help='path to clang-tidy binary') @@ -238,6 +244,8 @@ def main(): try: invocation = [args.clang_tidy_binary, '-list-checks'] + if args.allow_enabling_alpha_checkers: + invocation.append('-allow-enabling-analyzer-alpha-checkers') invocation.append('-p=' + build_path) if args.checks: invocation.append('-checks=' + args.checks) diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt index 1c2cbf398b7799ec36bc98aff871382a7ff754e2..b8e179855b9df174c72014dc5bc0f11feb575624 100644 --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(support) + # Configure the Features.inc file. if (NOT DEFINED CLANGD_BUILD_XPC) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -25,19 +27,8 @@ set(LLVM_LINK_COMPONENTS FrontendOpenMP ) -if(CLANG_BUILT_STANDALONE) - # needed to get HAVE_CXX_ATOMICS64_WITHOUT_LIB defined - include(CheckAtomic) -endif() - -set(CLANGD_ATOMIC_LIB "") -if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB OR NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) - list(APPEND CLANGD_ATOMIC_LIB "atomic") -endif() - add_clang_library(clangDaemon AST.cpp - Cancellation.cpp ClangdLSPServer.cpp ClangdServer.cpp CodeComplete.cpp @@ -45,7 +36,6 @@ add_clang_library(clangDaemon CollectMacros.cpp CompileCommands.cpp Compiler.cpp - Context.cpp Diagnostics.cpp DraftStore.cpp ExpectedTypes.cpp @@ -54,7 +44,6 @@ add_clang_library(clangDaemon FileDistance.cpp Format.cpp FS.cpp - FSProvider.cpp FormattedString.cpp FuzzyMatch.cpp GlobalCompilationDatabase.cpp @@ -63,7 +52,6 @@ add_clang_library(clangDaemon Hover.cpp IncludeFixer.cpp JSONTransport.cpp - Logger.cpp PathMapping.cpp Protocol.cpp Quality.cpp @@ -73,11 +61,8 @@ add_clang_library(clangDaemon Selection.cpp SemanticHighlighting.cpp SemanticSelection.cpp - Shutdown.cpp SourceCode.cpp QueryDriverDatabase.cpp - Threading.cpp - Trace.cpp TUScheduler.cpp URI.cpp XRefs.cpp @@ -128,8 +113,8 @@ add_clang_library(clangDaemon clangToolingInclusions clangToolingRefactoring clangToolingSyntax + clangdSupport ${LLVM_PTHREAD_LIB} - ${CLANGD_ATOMIC_LIB} ${ALL_CLANG_TIDY_CHECKS} ) @@ -140,7 +125,6 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") endif() add_subdirectory(tool) add_subdirectory(indexer) -add_subdirectory(index/dex/dexp) if (LLVM_INCLUDE_BENCHMARKS) add_subdirectory(benchmarks) @@ -160,5 +144,6 @@ set(GRPC_INSTALL_PATH "" CACHE PATH "Path to gRPC library manual installation.") if (CLANGD_ENABLE_REMOTE) include(FindGRPC) - add_subdirectory(index/remote) endif() +add_subdirectory(index/remote) +add_subdirectory(index/dex/dexp) diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index f58bfaf996481779a09a0d5be87b85727655f31c..4ca4f83ae39527f8f9c21330f3a36fdc1893be50 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "ClangdLSPServer.h" -#include "Context.h" #include "Diagnostics.h" #include "DraftStore.h" #include "FormattedString.h" @@ -16,9 +15,10 @@ #include "SemanticHighlighting.h" #include "SourceCode.h" #include "TUScheduler.h" -#include "Trace.h" #include "URI.h" #include "refactor/Tweak.h" +#include "support/Context.h" +#include "support/Trace.h" #include "clang/Basic/Version.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/ADT/ArrayRef.h" diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h index 9c35ca6bda3a6ec992849891ff34c3fbc1c85f65..c3da2f9a9457f31e25f47f74458166c874a35806 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.h +++ b/clang-tools-extra/clangd/ClangdLSPServer.h @@ -10,14 +10,14 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H #include "ClangdServer.h" -#include "Context.h" #include "DraftStore.h" #include "Features.inc" #include "FindSymbols.h" #include "GlobalCompilationDatabase.h" -#include "Path.h" #include "Protocol.h" #include "Transport.h" +#include "support/Context.h" +#include "support/Path.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSet.h" diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index c5148f81f3dfe5953281004892641b281ab72a8a..3dce7fec86c5a83b24195f3b2b0e2904b270426c 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -13,7 +13,6 @@ #include "FormattedString.h" #include "HeaderSourceSwitch.h" #include "Headers.h" -#include "Logger.h" #include "ParsedAST.h" #include "Preamble.h" #include "Protocol.h" @@ -21,13 +20,14 @@ #include "SemanticSelection.h" #include "SourceCode.h" #include "TUScheduler.h" -#include "Trace.h" #include "XRefs.h" #include "index/CanonicalIncludes.h" #include "index/FileIndex.h" #include "index/Merge.h" #include "refactor/Rename.h" #include "refactor/Tweak.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "clang/Format/Format.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index f6e7e0799d83b37eb5d382744ef1bb2eada40b04..d36dfd1e9a887d438a7b1e2b07fc4cdce7dfc4c5 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -10,11 +10,8 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H #include "../clang-tidy/ClangTidyOptions.h" -#include "Cancellation.h" #include "CodeComplete.h" -#include "FSProvider.h" #include "FormattedString.h" -#include "Function.h" #include "GlobalCompilationDatabase.h" #include "Hover.h" #include "Protocol.h" @@ -26,6 +23,9 @@ #include "index/Index.h" #include "refactor/Rename.h" #include "refactor/Tweak.h" +#include "support/Cancellation.h" +#include "support/FSProvider.h" +#include "support/Function.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/ADT/FunctionExtras.h" diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 3d9bfe509f2b55cfb43e66f6ebc66c41ae519b7c..d218d6b3459915ddb19fc413ed49009cc175e0f3 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -26,18 +26,18 @@ #include "FileDistance.h" #include "FuzzyMatch.h" #include "Headers.h" -#include "Logger.h" #include "Preamble.h" #include "Protocol.h" #include "Quality.h" #include "SourceCode.h" #include "TUScheduler.h" -#include "Threading.h" -#include "Trace.h" #include "URI.h" #include "index/Index.h" #include "index/Symbol.h" #include "index/SymbolOrigin.h" +#include "support/Logger.h" +#include "support/Threading.h" +#include "support/Trace.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/Basic/CharInfo.h" diff --git a/clang-tools-extra/clangd/CodeComplete.h b/clang-tools-extra/clangd/CodeComplete.h index 3adea47c89a111f8d8404f8c7f04c633173f6786..1e237048686274b6aee62800c7e56bec0246a3f8 100644 --- a/clang-tools-extra/clangd/CodeComplete.h +++ b/clang-tools-extra/clangd/CodeComplete.h @@ -16,13 +16,13 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H #include "Headers.h" -#include "Logger.h" -#include "Path.h" #include "Protocol.h" #include "Quality.h" #include "index/Index.h" #include "index/Symbol.h" #include "index/SymbolOrigin.h" +#include "support/Logger.h" +#include "support/Path.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/CodeCompleteOptions.h" #include "clang/Tooling/CompilationDatabase.h" diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index ae343d5fb3a58b42ec9871fcf5a0397c86d20c7c..84f72f5f58c72a1047b8955aa823459efe662a6a 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "CompileCommands.h" -#include "Logger.h" +#include "support/Logger.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "llvm/Support/FileSystem.h" diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp index eae753b5c9b36f049b6408128579516cd90cb544..957d7c382125ef626dd0120e22f8bc78e842f596 100644 --- a/clang-tools-extra/clangd/Compiler.cpp +++ b/clang-tools-extra/clangd/Compiler.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "Compiler.h" -#include "Logger.h" +#include "support/Logger.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/PCHContainerOperations.h" @@ -65,6 +65,15 @@ buildCompilerInvocation(const ParseInputs &Inputs, CI->getFrontendOpts().DisableFree = false; CI->getLangOpts()->CommentOpts.ParseAllComments = true; CI->getLangOpts()->RetainCommentsFromSystemHeaders = true; + + // Disable any dependency outputting, we don't want to generate files or write + // to stdout/stderr. + CI->getDependencyOutputOpts().ShowIncludesDest = + ShowIncludesDestination::None; + CI->getDependencyOutputOpts().OutputFile.clear(); + CI->getDependencyOutputOpts().HeaderIncludeOutputFile.clear(); + CI->getDependencyOutputOpts().DOTOutputFile.clear(); + CI->getDependencyOutputOpts().ModuleDependencyOutputDir.clear(); return CI; } diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index d72c2bd68ce89229a85f99596063d078ce68ba64..3558ca929798217d38b40ad535dff0436e56b715 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -9,9 +9,9 @@ #include "Diagnostics.h" #include "../clang-tidy/ClangTidyDiagnosticConsumer.h" #include "Compiler.h" -#include "Logger.h" #include "Protocol.h" #include "SourceCode.h" +#include "support/Logger.h" #include "clang/Basic/AllDiagnostics.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticIDs.h" diff --git a/clang-tools-extra/clangd/Diagnostics.h b/clang-tools-extra/clangd/Diagnostics.h index 7461f8529c2f606be763799ce39d9b44fcb8f42a..ebf86ba8716a18a3b2488a4151f5ddd1e29516e0 100644 --- a/clang-tools-extra/clangd/Diagnostics.h +++ b/clang-tools-extra/clangd/Diagnostics.h @@ -9,8 +9,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H -#include "Path.h" #include "Protocol.h" +#include "support/Path.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/ArrayRef.h" diff --git a/clang-tools-extra/clangd/DraftStore.cpp b/clang-tools-extra/clangd/DraftStore.cpp index 03867dcd286e3115bb6a64cf93a7571c5d4491e5..bef48ddfa37d60775500920ac24cf58dba0b6488 100644 --- a/clang-tools-extra/clangd/DraftStore.cpp +++ b/clang-tools-extra/clangd/DraftStore.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "DraftStore.h" -#include "Logger.h" #include "SourceCode.h" +#include "support/Logger.h" #include "llvm/Support/Errc.h" namespace clang { diff --git a/clang-tools-extra/clangd/DraftStore.h b/clang-tools-extra/clangd/DraftStore.h index babc679ed7639b5fd9574db362f312638d391569..3c2d0c6a4b0fa65e2a7b78760126cbfc69aca073 100644 --- a/clang-tools-extra/clangd/DraftStore.h +++ b/clang-tools-extra/clangd/DraftStore.h @@ -9,8 +9,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DRAFTSTORE_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DRAFTSTORE_H -#include "Path.h" #include "Protocol.h" +#include "support/Path.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" #include diff --git a/clang-tools-extra/clangd/FS.h b/clang-tools-extra/clangd/FS.h index 7b7f7cb25fac9432cd1ad42209dafbfc07f2c4a7..5994bdff9271e54b678c824e13d757711aca22f4 100644 --- a/clang-tools-extra/clangd/FS.h +++ b/clang-tools-extra/clangd/FS.h @@ -9,7 +9,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H -#include "Path.h" +#include "support/Path.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" diff --git a/clang-tools-extra/clangd/Features.inc.in b/clang-tools-extra/clangd/Features.inc.in index da75aa67a65b8d3582c6a595992611fbfd406898..6797232ddac7c5076def93a6fa6922aebef88228 100644 --- a/clang-tools-extra/clangd/Features.inc.in +++ b/clang-tools-extra/clangd/Features.inc.in @@ -1 +1,2 @@ #define CLANGD_BUILD_XPC @CLANGD_BUILD_XPC@ +#define CLANGD_ENABLE_REMOTE @CLANGD_ENABLE_REMOTE@ diff --git a/clang-tools-extra/clangd/FileDistance.cpp b/clang-tools-extra/clangd/FileDistance.cpp index a9ce3e514bcc18514cc1525addedf8f539dabeb6..584c64d077e17e15f7d5fe7bd7800e8459acf6ec 100644 --- a/clang-tools-extra/clangd/FileDistance.cpp +++ b/clang-tools-extra/clangd/FileDistance.cpp @@ -31,7 +31,7 @@ //===-------------------------------------------------------------------------// #include "FileDistance.h" -#include "Logger.h" +#include "support/Logger.h" #include "llvm/ADT/STLExtras.h" #include diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp index 06c124c0b35b1be2e117cb418847ca7226e8cc24..58e2ee1e21c77f7a886034af8bf9fb6cabbb95bc 100644 --- a/clang-tools-extra/clangd/FindSymbols.cpp +++ b/clang-tools-extra/clangd/FindSymbols.cpp @@ -9,11 +9,11 @@ #include "AST.h" #include "FuzzyMatch.h" -#include "Logger.h" #include "ParsedAST.h" #include "Quality.h" #include "SourceCode.h" #include "index/Index.h" +#include "support/Logger.h" #include "clang/AST/DeclTemplate.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/IndexSymbol.h" diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 1ff20e6e4bc17258dc571340028739755d915914..2813e30b4335a2fbc67cf275f2d7ee2da1f37458 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -8,7 +8,7 @@ #include "FindTarget.h" #include "AST.h" -#include "Logger.h" +#include "support/Logger.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -860,15 +860,17 @@ public: // TemplateArgumentLoc is the only way to get locations for references to // template template parameters. bool TraverseTemplateArgumentLoc(TemplateArgumentLoc A) { + llvm::SmallVector Targets; switch (A.getArgument().getKind()) { case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: + if (const auto *D = A.getArgument() + .getAsTemplateOrTemplatePattern() + .getAsTemplateDecl()) + Targets.push_back(D); reportReference(ReferenceLoc{A.getTemplateQualifierLoc(), A.getTemplateNameLoc(), - /*IsDecl=*/false, - {A.getArgument() - .getAsTemplateOrTemplatePattern() - .getAsTemplateDecl()}}, + /*IsDecl=*/false, Targets}, DynTypedNode::create(A.getArgument())); break; case TemplateArgument::Declaration: diff --git a/clang-tools-extra/clangd/Format.cpp b/clang-tools-extra/clangd/Format.cpp index b8b9d8e627d2930da51d8f9b88fae73dcdf3251d..052cf74f8bd000ee24f934473ef571a681fbf936 100644 --- a/clang-tools-extra/clangd/Format.cpp +++ b/clang-tools-extra/clangd/Format.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// #include "Format.h" -#include "Logger.h" -#include "clang/Basic/SourceManager.h" +#include "support/Logger.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" #include "clang/Format/Format.h" #include "clang/Lex/Lexer.h" #include "clang/Tooling/Core/Replacement.h" diff --git a/clang-tools-extra/clangd/FormattedString.cpp b/clang-tools-extra/clangd/FormattedString.cpp index d3dbdbba17bc3ef654adbb82d43cc4c025c02559..81de6a8be93c961e90142546b172d7ced537a609 100644 --- a/clang-tools-extra/clangd/FormattedString.cpp +++ b/clang-tools-extra/clangd/FormattedString.cpp @@ -216,23 +216,10 @@ std::string getMarkerForCodeBlock(llvm::StringRef Input) { } // Trims the input and concatenates whitespace blocks into a single ` `. -std::string canonicalizeSpaces(std::string Input) { - // Goes over the string and preserves only a single ` ` for any whitespace - // chunks, the rest is moved to the end of the string and dropped in the end. - auto WritePtr = Input.begin(); +std::string canonicalizeSpaces(llvm::StringRef Input) { llvm::SmallVector Words; llvm::SplitString(Input, Words); - if (Words.empty()) - return ""; - // Go over each word and add it to the string. - for (llvm::StringRef Word : Words) { - if (WritePtr > Input.begin()) - *WritePtr++ = ' '; // Separate from previous block. - llvm::for_each(Word, [&WritePtr](const char C) { *WritePtr++ = C; }); - } - // Get rid of extra spaces. - Input.resize(WritePtr - Input.begin()); - return Input; + return llvm::join(Words, " "); } std::string renderBlocks(llvm::ArrayRef> Children, @@ -398,24 +385,24 @@ void BulletList::renderPlainText(llvm::raw_ostream &OS) const { } } -Paragraph &Paragraph::appendText(std::string Text) { - Text = canonicalizeSpaces(std::move(Text)); - if (Text.empty()) +Paragraph &Paragraph::appendText(llvm::StringRef Text) { + std::string Norm = canonicalizeSpaces(Text); + if (Norm.empty()) return *this; Chunks.emplace_back(); Chunk &C = Chunks.back(); - C.Contents = std::move(Text); + C.Contents = std::move(Norm); C.Kind = Chunk::PlainText; return *this; } -Paragraph &Paragraph::appendCode(std::string Code) { - Code = canonicalizeSpaces(std::move(Code)); - if (Code.empty()) +Paragraph &Paragraph::appendCode(llvm::StringRef Code) { + std::string Norm = canonicalizeSpaces(std::move(Code)); + if (Norm.empty()) return *this; Chunks.emplace_back(); Chunk &C = Chunks.back(); - C.Contents = std::move(Code); + C.Contents = std::move(Norm); C.Kind = Chunk::InlineCode; return *this; } diff --git a/clang-tools-extra/clangd/FormattedString.h b/clang-tools-extra/clangd/FormattedString.h index fe864ba575681fd6097179f838f4a17b22a5a1ab..8c522d060c4f25054162895c74d7f1d5a3a5ae77 100644 --- a/clang-tools-extra/clangd/FormattedString.h +++ b/clang-tools-extra/clangd/FormattedString.h @@ -46,10 +46,10 @@ public: void renderPlainText(llvm::raw_ostream &OS) const override; /// Append plain text to the end of the string. - Paragraph &appendText(std::string Text); + Paragraph &appendText(llvm::StringRef Text); /// Append inline code, this translates to the ` block in markdown. - Paragraph &appendCode(std::string Code); + Paragraph &appendCode(llvm::StringRef Code); private: struct Chunk { diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index aa6727fc20f575cd343aaa0e98cc2a96b4c965d9..5e75864ec8d443e8747fed6eb4786a9917a2a3f3 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -8,8 +8,8 @@ #include "GlobalCompilationDatabase.h" #include "FS.h" -#include "Logger.h" -#include "Path.h" +#include "support/Logger.h" +#include "support/Path.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" @@ -110,14 +110,24 @@ static bool pathEqual(PathRef A, PathRef B) { DirectoryBasedGlobalCompilationDatabase::CachedCDB & DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const { // FIXME(ibiryukov): Invalidate cached compilation databases on changes - // FIXME(sammccall): this function hot, avoid copying key when hitting cache. auto Key = maybeCaseFoldPath(Dir); auto R = CompilationDatabases.try_emplace(Key); if (R.second) { // Cache miss, try to load CDB. CachedCDB &Entry = R.first->second; std::string Error; - Entry.CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error); Entry.Path = std::string(Dir); + Entry.CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error); + // Check for $src/build, the conventional CMake build root. + // Probe existence first to avoid each plugin doing IO if it doesn't exist. + if (!CompileCommandsDir && !Entry.CDB) { + llvm::SmallString<256> BuildDir = Dir; + llvm::sys::path::append(BuildDir, "build"); + if (llvm::sys::fs::is_directory(BuildDir)) { + vlog("Found candidate build directory {0}", BuildDir); + Entry.CDB = + tooling::CompilationDatabase::loadFromDirectory(BuildDir, Error); + } + } if (Entry.CDB) log("Loaded compilation database from {0}", Dir); } diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h index 2fc754927fd95924788eb4cf046c03dcb66ef964..e9a5417d9d69bc0cbd888ca3515dea29ae563662 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h @@ -10,8 +10,8 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H #include "CompileCommands.h" -#include "Function.h" -#include "Path.h" +#include "support/Function.h" +#include "support/Path.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/Optional.h" diff --git a/clang-tools-extra/clangd/HeaderSourceSwitch.cpp b/clang-tools-extra/clangd/HeaderSourceSwitch.cpp index 1490d3ebe5c0d331412ae5b079e063806e1c8e25..3ebf0542dcf0fc2e7bd06a5473f76d9c450a4c2b 100644 --- a/clang-tools-extra/clangd/HeaderSourceSwitch.cpp +++ b/clang-tools-extra/clangd/HeaderSourceSwitch.cpp @@ -8,9 +8,9 @@ #include "HeaderSourceSwitch.h" #include "AST.h" -#include "Logger.h" #include "SourceCode.h" #include "index/SymbolCollector.h" +#include "support/Logger.h" #include "clang/AST/Decl.h" namespace clang { diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index dd4cafd2ddfc263b3705c1f8e783a014c30daf31..c0e19f2795a04c0b1720bd200c707d521c7d215e 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -8,8 +8,8 @@ #include "Headers.h" #include "Compiler.h" -#include "Logger.h" #include "SourceCode.h" +#include "support/Logger.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" diff --git a/clang-tools-extra/clangd/Headers.h b/clang-tools-extra/clangd/Headers.h index 1f3968765d838be2c25d6e2a3da6df9a754468a4..2ffa902d740f93b2d68ec9a5a3a7c7922bdfef9a 100644 --- a/clang-tools-extra/clangd/Headers.h +++ b/clang-tools-extra/clangd/Headers.h @@ -9,10 +9,10 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H -#include "Path.h" #include "Protocol.h" #include "SourceCode.h" #include "index/Symbol.h" +#include "support/Path.h" #include "clang/Basic/TokenKinds.h" #include "clang/Format/Format.h" #include "clang/Lex/HeaderSearch.h" diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index ba8fcd4687b03c7192c4f1d4b1cf17bef7e7735d..3a66130ea153fab5f097e0b1a81e055be117d023 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -12,11 +12,11 @@ #include "CodeCompletionStrings.h" #include "FindTarget.h" #include "FormattedString.h" -#include "Logger.h" #include "ParsedAST.h" #include "Selection.h" #include "SourceCode.h" #include "index/SymbolCollector.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" @@ -772,7 +772,7 @@ markup::Document HoverInfo::present() const { // https://github.com/microsoft/vscode/issues/88417 for details. markup::Paragraph &Header = Output.addHeading(3); if (Kind != index::SymbolKind::Unknown) - Header.appendText(std::string(index::getSymbolKindString(Kind))); + Header.appendText(index::getSymbolKindString(Kind)); assert(!Name.empty() && "hover triggered on a nameless symbol"); Header.appendCode(Name); @@ -809,10 +809,11 @@ markup::Document HoverInfo::present() const { if (Offset) Output.addParagraph().appendText( - llvm::formatv("Offset: {0} byte{1}", *Offset, *Offset == 1 ? "" : "s")); + llvm::formatv("Offset: {0} byte{1}", *Offset, *Offset == 1 ? "" : "s") + .str()); if (Size) Output.addParagraph().appendText( - llvm::formatv("Size: {0} byte{1}", *Size, *Size == 1 ? "" : "s")); + llvm::formatv("Size: {0} byte{1}", *Size, *Size == 1 ? "" : "s").str()); if (!Documentation.empty()) parseDocumentation(Documentation, Output); @@ -838,6 +839,52 @@ markup::Document HoverInfo::present() const { return Output; } +// If the backtick at `Offset` starts a probable quoted range, return the range +// (including the quotes). +llvm::Optional getBacktickQuoteRange(llvm::StringRef Line, + unsigned Offset) { + assert(Line[Offset] == '`'); + + // The open-quote is usually preceded by whitespace. + llvm::StringRef Prefix = Line.substr(0, Offset); + constexpr llvm::StringLiteral BeforeStartChars = " \t(="; + if (!Prefix.empty() && !BeforeStartChars.contains(Prefix.back())) + return llvm::None; + + // The quoted string must be nonempty and usually has no leading/trailing ws. + auto Next = Line.find('`', Offset + 1); + if (Next == llvm::StringRef::npos) + return llvm::None; + llvm::StringRef Contents = Line.slice(Offset + 1, Next); + if (Contents.empty() || isWhitespace(Contents.front()) || + isWhitespace(Contents.back())) + return llvm::None; + + // The close-quote is usually followed by whitespace or punctuation. + llvm::StringRef Suffix = Line.substr(Next + 1); + constexpr llvm::StringLiteral AfterEndChars = " \t)=.,;:"; + if (!Suffix.empty() && !AfterEndChars.contains(Suffix.front())) + return llvm::None; + + return Line.slice(Offset, Next+1); +} + +void parseDocumentationLine(llvm::StringRef Line, markup::Paragraph &Out) { + // Probably this is appendText(Line), but scan for something interesting. + for (unsigned I = 0; I < Line.size(); ++I) { + switch (Line[I]) { + case '`': + if (auto Range = getBacktickQuoteRange(Line, I)) { + Out.appendText(Line.substr(0, I)); + Out.appendCode(Range->trim("`")); + return parseDocumentationLine(Line.substr(I+Range->size()), Out); + } + break; + } + } + Out.appendText(Line); +} + void parseDocumentation(llvm::StringRef Input, markup::Document &Output) { std::vector ParagraphLines; auto FlushParagraph = [&] { @@ -845,7 +892,7 @@ void parseDocumentation(llvm::StringRef Input, markup::Document &Output) { return; auto &P = Output.addParagraph(); for (llvm::StringRef Line : ParagraphLines) - P.appendText(Line.str()); + parseDocumentationLine(Line, P); ParagraphLines.clear(); }; diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp index 45fb07ad06a1ae61399697575382866cf104d9e9..945f4eced88c4772ea3c0347bb445b87fab1126f 100644 --- a/clang-tools-extra/clangd/IncludeFixer.cpp +++ b/clang-tools-extra/clangd/IncludeFixer.cpp @@ -9,11 +9,11 @@ #include "IncludeFixer.h" #include "AST.h" #include "Diagnostics.h" -#include "Logger.h" #include "SourceCode.h" -#include "Trace.h" #include "index/Index.h" #include "index/Symbol.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" diff --git a/clang-tools-extra/clangd/JSONTransport.cpp b/clang-tools-extra/clangd/JSONTransport.cpp index a9254732562bca32fe6ac3bcbe84211f1087c8d9..fa86baf6c581600eaca4a02f5bfa3a052034c5d2 100644 --- a/clang-tools-extra/clangd/JSONTransport.cpp +++ b/clang-tools-extra/clangd/JSONTransport.cpp @@ -5,11 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "Cancellation.h" -#include "Logger.h" #include "Protocol.h" // For LSPError -#include "Shutdown.h" #include "Transport.h" +#include "support/Cancellation.h" +#include "support/Logger.h" +#include "support/Shutdown.h" #include "llvm/Support/Errno.h" #include "llvm/Support/Error.h" diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index fc631da3a317cf4ee7d43f47670f0c72f01ab223..61221aaa1491e2e9f75962478db8b1713dc6d34d 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -14,11 +14,11 @@ #include "Diagnostics.h" #include "Headers.h" #include "IncludeFixer.h" -#include "Logger.h" #include "SourceCode.h" -#include "Trace.h" #include "index/CanonicalIncludes.h" #include "index/Index.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/Basic/LangOptions.h" @@ -239,13 +239,22 @@ void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS) { } llvm::Optional -ParsedAST::build(llvm::StringRef Version, +ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr CI, llvm::ArrayRef CompilerInvocationDiags, - std::shared_ptr Preamble, - std::unique_ptr Buffer, - llvm::IntrusiveRefCntPtr VFS, - const SymbolIndex *Index, const ParseOptions &Opts) { + std::shared_ptr Preamble) { + trace::Span Tracer("BuildAST"); + SPAN_ATTACH(Tracer, "File", Filename); + + auto VFS = Inputs.FS; + if (Preamble && Preamble->StatCache) + VFS = Preamble->StatCache->getConsumingFS(std::move(VFS)); + if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) { + log("Couldn't set working directory when building the preamble."); + // We proceed anyway, our lit-tests rely on results for non-existing working + // dirs. + } + assert(CI); // Command-line parsing sets DisableFree to true by default, but we don't want // to leak memory in clangd. @@ -255,15 +264,17 @@ ParsedAST::build(llvm::StringRef Version, // Recovery expression currently only works for C++. if (CI->getLangOpts()->CPlusPlus) - CI->getLangOpts()->RecoveryAST = Opts.BuildRecoveryAST; + CI->getLangOpts()->RecoveryAST = Inputs.Opts.BuildRecoveryAST; + // This is on-by-default in windows to allow parsing SDK headers, but it + // breaks many features. Disable it for the main-file (not preamble). + CI->getLangOpts()->DelayedTemplateParsing = false; StoreDiags ASTDiags; - std::string Content = std::string(Buffer->getBuffer()); - std::string Filename = - std::string(Buffer->getBufferIdentifier()); // Absolute. - auto Clang = prepareCompilerInstance(std::move(CI), PreamblePCH, - std::move(Buffer), VFS, ASTDiags); + auto Clang = prepareCompilerInstance( + std::move(CI), PreamblePCH, + llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, Filename), VFS, + ASTDiags); if (!Clang) return None; @@ -287,12 +298,12 @@ ParsedAST::build(llvm::StringRef Version, { trace::Span Tracer("ClangTidyInit"); dlog("ClangTidy configuration for file {0}: {1}", Filename, - tidy::configurationAsText(Opts.ClangTidyOpts)); + tidy::configurationAsText(Inputs.Opts.ClangTidyOpts)); tidy::ClangTidyCheckFactories CTFactories; for (const auto &E : tidy::ClangTidyModuleRegistry::entries()) E.instantiate()->addCheckFactories(CTFactories); CTContext.emplace(std::make_unique( - tidy::ClangTidyGlobalOptions(), Opts.ClangTidyOpts)); + tidy::ClangTidyGlobalOptions(), Inputs.Opts.ClangTidyOpts)); CTContext->setDiagnosticsEngine(&Clang->getDiagnostics()); CTContext->setASTContext(&Clang->getASTContext()); CTContext->setCurrentFile(Filename); @@ -342,16 +353,17 @@ ParsedAST::build(llvm::StringRef Version, // (e.g. incomplete type) and attach include insertion fixes to diagnostics. llvm::Optional FixIncludes; auto BuildDir = VFS->getCurrentWorkingDirectory(); - if (Opts.SuggestMissingIncludes && Index && !BuildDir.getError()) { - auto Style = getFormatStyleForFile(Filename, Content, VFS.get()); + if (Inputs.Opts.SuggestMissingIncludes && Inputs.Index && + !BuildDir.getError()) { + auto Style = getFormatStyleForFile(Filename, Inputs.Contents, VFS.get()); auto Inserter = std::make_shared( - Filename, Content, Style, BuildDir.get(), + Filename, Inputs.Contents, Style, BuildDir.get(), &Clang->getPreprocessor().getHeaderSearchInfo()); if (Preamble) { for (const auto &Inc : Preamble->Includes.MainFileIncludes) Inserter->addExisting(Inc); } - FixIncludes.emplace(Filename, Inserter, *Index, + FixIncludes.emplace(Filename, Inserter, *Inputs.Index, /*IndexRequestLimit=*/5); ASTDiags.contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl, const clang::Diagnostic &Info) { @@ -431,7 +443,7 @@ ParsedAST::build(llvm::StringRef Version, std::vector D = ASTDiags.take(CTContext.getPointer()); Diags.insert(Diags.end(), D.begin(), D.end()); } - return ParsedAST(Version, std::move(Preamble), std::move(Clang), + return ParsedAST(Inputs.Version, std::move(Preamble), std::move(Clang), std::move(Action), std::move(Tokens), std::move(Macros), std::move(ParsedDecls), std::move(Diags), std::move(Includes), std::move(CanonIncludes)); @@ -533,28 +545,5 @@ ParsedAST::ParsedAST(llvm::StringRef Version, assert(this->Action); } -llvm::Optional -buildAST(PathRef FileName, std::unique_ptr Invocation, - llvm::ArrayRef CompilerInvocationDiags, - const ParseInputs &Inputs, - std::shared_ptr Preamble) { - trace::Span Tracer("BuildAST"); - SPAN_ATTACH(Tracer, "File", FileName); - - auto VFS = Inputs.FS; - if (Preamble && Preamble->StatCache) - VFS = Preamble->StatCache->getConsumingFS(std::move(VFS)); - if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) { - log("Couldn't set working directory when building the preamble."); - // We proceed anyway, our lit-tests rely on results for non-existing working - // dirs. - } - - return ParsedAST::build( - Inputs.Version, std::move(Invocation), CompilerInvocationDiags, Preamble, - llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, FileName), - std::move(VFS), Inputs.Index, Inputs.Opts); -} - } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/ParsedAST.h b/clang-tools-extra/clangd/ParsedAST.h index 8620f31ff1e50ff15293bd47061f15f215331eeb..d90f77f9263b3586fb41df88b42cd510a1b73c97 100644 --- a/clang-tools-extra/clangd/ParsedAST.h +++ b/clang-tools-extra/clangd/ParsedAST.h @@ -15,7 +15,6 @@ // - capturing diagnostics for later access // - running clang-tidy checks checks // -// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H @@ -25,9 +24,9 @@ #include "Compiler.h" #include "Diagnostics.h" #include "Headers.h" -#include "Path.h" #include "Preamble.h" #include "index/CanonicalIncludes.h" +#include "support/Path.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/PrecompiledPreamble.h" #include "clang/Lex/Preprocessor.h" @@ -45,15 +44,14 @@ class SymbolIndex; /// Stores and provides access to parsed AST. class ParsedAST { public: - /// Attempts to run Clang and store parsed AST. If \p Preamble is non-null - /// it is reused during parsing. + /// Attempts to run Clang and store the parsed AST. + /// If \p Preamble is non-null it is reused during parsing. + /// This function does not check if preamble is valid to reuse. static llvm::Optional - build(llvm::StringRef Version, std::unique_ptr CI, + build(llvm::StringRef Filename, const ParseInputs &Inputs, + std::unique_ptr CI, llvm::ArrayRef CompilerInvocationDiags, - std::shared_ptr Preamble, - std::unique_ptr Buffer, - llvm::IntrusiveRefCntPtr VFS, - const SymbolIndex *Index, const ParseOptions &Opts); + std::shared_ptr Preamble); ParsedAST(ParsedAST &&Other); ParsedAST &operator=(ParsedAST &&Other); @@ -141,15 +139,6 @@ private: CanonicalIncludes CanonIncludes; }; -/// Build an AST from provided user inputs. This function does not check if -/// preamble can be reused, as this function expects that \p Preamble is the -/// result of calling buildPreamble. -llvm::Optional -buildAST(PathRef FileName, std::unique_ptr Invocation, - llvm::ArrayRef CompilerInvocationDiags, - const ParseInputs &Inputs, - std::shared_ptr Preamble); - /// For testing/debugging purposes. Note that this method deserializes all /// unserialized Decls, so use with care. void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS); diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp index 8392748227b4a329cf7e5561a0d76362d6ec9d16..2768bd1ec6a08594ed6520d50c17588472e8346c 100644 --- a/clang-tools-extra/clangd/Preamble.cpp +++ b/clang-tools-extra/clangd/Preamble.cpp @@ -9,8 +9,8 @@ #include "Preamble.h" #include "Compiler.h" #include "Headers.h" -#include "Logger.h" -#include "Trace.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" diff --git a/clang-tools-extra/clangd/Preamble.h b/clang-tools-extra/clangd/Preamble.h index 10c292a71f388413ba65eb007ec5284fd787c1a6..f2e1ba98f33264d1e1dc5b3b932e187fc6ebffde 100644 --- a/clang-tools-extra/clangd/Preamble.h +++ b/clang-tools-extra/clangd/Preamble.h @@ -27,8 +27,8 @@ #include "Diagnostics.h" #include "FS.h" #include "Headers.h" -#include "Path.h" #include "index/CanonicalIncludes.h" +#include "support/Path.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PrecompiledPreamble.h" #include "clang/Tooling/CompilationDatabase.h" diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index b0c7ce2acb337497dd6faac59c5cd0448418bc49..314e6b0bbabc4f639158f2ad10e1dd366dbb2478 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// #include "Protocol.h" -#include "Logger.h" #include "URI.h" +#include "support/Logger.h" #include "clang/Basic/LLVM.h" #include "clang/Index/IndexSymbol.h" #include "llvm/ADT/Hashing.h" diff --git a/clang-tools-extra/clangd/QueryDriverDatabase.cpp b/clang-tools-extra/clangd/QueryDriverDatabase.cpp index d6502c6b84badfcb51480602179470d06edd2305..2ab217dac1559069898b93b287a85d88c0287d98 100644 --- a/clang-tools-extra/clangd/QueryDriverDatabase.cpp +++ b/clang-tools-extra/clangd/QueryDriverDatabase.cpp @@ -30,9 +30,9 @@ // in the paths that are explicitly whitelisted by the user. #include "GlobalCompilationDatabase.h" -#include "Logger.h" -#include "Path.h" -#include "Trace.h" +#include "support/Logger.h" +#include "support/Path.h" +#include "support/Trace.h" #include "clang/Driver/Types.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/DenseMap.h" diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index b4565446c8ec9d11ca88a04860a82924c51bf816..7d52714ad3fa48110681c2dcfff7ad2e4ce180c1 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "Selection.h" -#include "Logger.h" #include "SourceCode.h" +#include "support/Logger.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index baf13755ecf716a0441cc57475c19c407a25d52d..d2470da601408bfb54b5e41775bf40025d606b19 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -8,10 +8,10 @@ #include "SemanticHighlighting.h" #include "FindTarget.h" -#include "Logger.h" #include "ParsedAST.h" #include "Protocol.h" #include "SourceCode.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index 1943784bfd187f13a28642de0029a4cd71037cd4..d50968bae19b75f7b85a4f701600a041d72b19d0 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "SourceCode.h" -#include "Context.h" #include "FuzzyMatch.h" -#include "Logger.h" #include "Protocol.h" #include "refactor/Tweak.h" +#include "support/Context.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" @@ -855,6 +855,96 @@ llvm::StringSet<> collectWords(llvm::StringRef Content) { return Result; } +static bool isLikelyIdentifier(llvm::StringRef Word, llvm::StringRef Before, + llvm::StringRef After) { + // `foo` is an identifier. + if (Before.endswith("`") && After.startswith("`")) + return true; + // In foo::bar, both foo and bar are identifiers. + if (Before.endswith("::") || After.startswith("::")) + return true; + // Doxygen tags like \c foo indicate identifiers. + // Don't search too far back. + // This duplicates clang's doxygen parser, revisit if it gets complicated. + Before = Before.take_back(100); // Don't search too far back. + auto Pos = Before.find_last_of("\\@"); + if (Pos != llvm::StringRef::npos) { + llvm::StringRef Tag = Before.substr(Pos + 1).rtrim(' '); + if (Tag == "p" || Tag == "c" || Tag == "class" || Tag == "tparam" || + Tag == "param" || Tag == "param[in]" || Tag == "param[out]" || + Tag == "param[in,out]" || Tag == "retval" || Tag == "throw" || + Tag == "throws" || Tag == "link") + return true; + } + + // Word contains underscore. + // This handles things like snake_case and MACRO_CASE. + if (Word.contains('_')) { + return true; + } + // Word contains capital letter other than at beginning. + // This handles things like lowerCamel and UpperCamel. + // The check for also containing a lowercase letter is to rule out + // initialisms like "HTTP". + bool HasLower = Word.find_if(clang::isLowercase) != StringRef::npos; + bool HasUpper = Word.substr(1).find_if(clang::isUppercase) != StringRef::npos; + if (HasLower && HasUpper) { + return true; + } + // FIXME: consider mid-sentence Capitalization? + return false; +} + +llvm::Optional SpelledWord::touching(SourceLocation SpelledLoc, + const syntax::TokenBuffer &TB, + const LangOptions &LangOpts) { + const auto &SM = TB.sourceManager(); + auto Touching = syntax::spelledTokensTouching(SpelledLoc, TB); + for (const auto &T : Touching) { + // If the token is an identifier or a keyword, don't use any heuristics. + if (tok::isAnyIdentifier(T.kind()) || tok::getKeywordSpelling(T.kind())) { + SpelledWord Result; + Result.Location = T.location(); + Result.Text = T.text(SM); + Result.LikelyIdentifier = tok::isAnyIdentifier(T.kind()); + Result.PartOfSpelledToken = &T; + Result.SpelledToken = &T; + auto Expanded = + TB.expandedTokens(SM.getMacroArgExpandedLocation(T.location())); + if (Expanded.size() == 1 && Expanded.front().text(SM) == Result.Text) + Result.ExpandedToken = &Expanded.front(); + return Result; + } + } + FileID File; + unsigned Offset; + std::tie(File, Offset) = SM.getDecomposedLoc(SpelledLoc); + bool Invalid = false; + llvm::StringRef Code = SM.getBufferData(File, &Invalid); + if (Invalid) + return llvm::None; + unsigned B = Offset, E = Offset; + while (B > 0 && isIdentifierBody(Code[B - 1])) + --B; + while (E < Code.size() && isIdentifierBody(Code[E])) + ++E; + if (B == E) + return llvm::None; + + SpelledWord Result; + Result.Location = SM.getComposedLoc(File, B); + Result.Text = Code.slice(B, E); + Result.LikelyIdentifier = + isLikelyIdentifier(Result.Text, Code.substr(0, B), Code.substr(E)) && + // should not be a keyword + tok::isAnyIdentifier( + IdentifierTable(LangOpts).get(Result.Text).getTokenID()); + for (const auto &T : Touching) + if (T.location() <= Result.Location) + Result.PartOfSpelledToken = &T; + return Result; +} + llvm::Optional locateMacroAt(const syntax::Token &SpelledTok, Preprocessor &PP) { SourceLocation Loc = SpelledTok.location(); diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h index dfa685fdd79591cc83511e7feb898f6029567606..c00cc17ac9bcfce3aa5e383b85e5f42e1a98f133 100644 --- a/clang-tools-extra/clangd/SourceCode.h +++ b/clang-tools-extra/clangd/SourceCode.h @@ -13,8 +13,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H -#include "Context.h" #include "Protocol.h" +#include "support/Context.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" @@ -216,6 +216,35 @@ std::vector collectIdentifierRanges(llvm::StringRef Identifier, /// - drops stopwords like "get" and "for" llvm::StringSet<> collectWords(llvm::StringRef Content); +// Something that looks like a word in the source code. +// Could be a "real" token that's "live" in the AST, a spelled token consumed by +// the preprocessor, or part of a spelled token (e.g. word in a comment). +struct SpelledWord { + // (Spelling) location of the start of the word. + SourceLocation Location; + // The range of the word itself, excluding any quotes. + // This is a subrange of the file buffer. + llvm::StringRef Text; + // Whether this word is likely to refer to an identifier. True if: + // - the word is a spelled identifier token + // - Text is identifier-like (e.g. "foo_bar") + // - Text is surrounded by backticks (e.g. Foo in "// returns `Foo`") + bool LikelyIdentifier = false; + // Set if the word is contained in a token spelled in the file. + // (This should always be true, but comments aren't retained by TokenBuffer). + const syntax::Token *PartOfSpelledToken = nullptr; + // Set if the word is exactly a token spelled in the file. + const syntax::Token *SpelledToken = nullptr; + // Set if the word is a token spelled in the file, and that token survives + // preprocessing to emit an expanded token spelled the same way. + const syntax::Token *ExpandedToken = nullptr; + + // Find the unique word that contains SpelledLoc or starts/ends there. + static llvm::Optional touching(SourceLocation SpelledLoc, + const syntax::TokenBuffer &TB, + const LangOptions &LangOpts); +}; + /// Heuristically determine namespaces visible at a point, without parsing Code. /// This considers using-directives and enclosing namespace-declarations that /// are visible (and not obfuscated) in the file itself (not headers). diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp index 2f2abb59ab3cb4452c9e6f2e681cc80e26891fdc..db5ac85ce7fcd41d5aa48df4433a2bc3ca4c4d19 100644 --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -47,18 +47,18 @@ // requests will receive latest build preamble, which might possibly be stale. #include "TUScheduler.h" -#include "Cancellation.h" #include "Compiler.h" -#include "Context.h" #include "Diagnostics.h" #include "GlobalCompilationDatabase.h" -#include "Logger.h" #include "ParsedAST.h" -#include "Path.h" #include "Preamble.h" -#include "Threading.h" -#include "Trace.h" #include "index/CanonicalIncludes.h" +#include "support/Cancellation.h" +#include "support/Context.h" +#include "support/Logger.h" +#include "support/Path.h" +#include "support/Threading.h" +#include "support/Trace.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/FunctionExtras.h" @@ -665,9 +665,9 @@ void ASTWorker::runWithAST( // return a compatible preamble as ASTWorker::update blocks. llvm::Optional NewAST; if (Invocation) { - NewAST = buildAST(FileName, std::move(Invocation), - CompilerInvocationDiagConsumer.take(), FileInputs, - getPossiblyStalePreamble()); + NewAST = ParsedAST::build(FileName, FileInputs, std::move(Invocation), + CompilerInvocationDiagConsumer.take(), + getPossiblyStalePreamble()); ++ASTBuildCount; } AST = NewAST ? std::make_unique(std::move(*NewAST)) : nullptr; @@ -804,8 +804,8 @@ void ASTWorker::generateDiagnostics( llvm::Optional> AST = IdleASTs.take(this); if (!AST || !InputsAreLatest) { auto RebuildStartTime = DebouncePolicy::clock::now(); - llvm::Optional NewAST = buildAST( - FileName, std::move(Invocation), CIDiags, Inputs, LatestPreamble); + llvm::Optional NewAST = ParsedAST::build( + FileName, Inputs, std::move(Invocation), CIDiags, LatestPreamble); auto RebuildDuration = DebouncePolicy::clock::now() - RebuildStartTime; ++ASTBuildCount; // Try to record the AST-build time, to inform future update debouncing. diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h index 48ed2c76f5461347494c352dbb90fa94cdd2c67e..f24a777d5836f52c00aaeb2e32c147f7dedbbedd 100644 --- a/clang-tools-extra/clangd/TUScheduler.h +++ b/clang-tools-extra/clangd/TUScheduler.h @@ -11,11 +11,11 @@ #include "Compiler.h" #include "Diagnostics.h" -#include "Function.h" #include "GlobalCompilationDatabase.h" -#include "Path.h" -#include "Threading.h" #include "index/CanonicalIncludes.h" +#include "support/Function.h" +#include "support/Path.h" +#include "support/Threading.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 2e2e6602c8d3e29f26f595f1f939912d2177b998..441856457e3b5081f7a28103a65bc9535b451fa2 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -10,7 +10,6 @@ #include "CodeCompletionStrings.h" #include "FindSymbols.h" #include "FindTarget.h" -#include "Logger.h" #include "ParsedAST.h" #include "Protocol.h" #include "Quality.h" @@ -21,7 +20,9 @@ #include "index/Merge.h" #include "index/Relation.h" #include "index/SymbolLocation.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Attr.h" #include "clang/AST/Attrs.inc" #include "clang/AST/Decl.h" @@ -34,6 +35,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/IndexSymbol.h" #include "clang/Index/IndexingAction.h" @@ -48,6 +50,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -137,17 +140,20 @@ SymbolLocation getPreferredLocation(const Location &ASTLoc, return Merged.CanonicalDeclaration; } -std::vector getDeclAtPosition(ParsedAST &AST, - SourceLocation Pos, - DeclRelationSet Relations) { +std::vector +getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, DeclRelationSet Relations, + ASTNodeKind *NodeKind = nullptr) { unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(Pos).second; std::vector Result; SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset, Offset, [&](SelectionTree ST) { if (const SelectionTree::Node *N = - ST.commonAncestor()) + ST.commonAncestor()) { + if (NodeKind) + *NodeKind = N->ASTNode.getNodeKind(); llvm::copy(targetDecl(N->ASTNode, Relations), std::back_inserter(Result)); + } return !Result.empty(); }); return Result; @@ -219,7 +225,7 @@ locateMacroReferent(const syntax::Token &TouchedIdentifier, ParsedAST &AST, std::vector locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, ParsedAST &AST, llvm::StringRef MainFilePath, - const SymbolIndex *Index) { + const SymbolIndex *Index, ASTNodeKind *NodeKind) { const SourceManager &SM = AST.getSourceManager(); // Results follow the order of Symbols.Decls. std::vector Result; @@ -248,7 +254,8 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, // Emit all symbol locations (declaration or definition) from AST. DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias; - for (const NamedDecl *D : getDeclAtPosition(AST, CurLoc, Relations)) { + for (const NamedDecl *D : + getDeclAtPosition(AST, CurLoc, Relations, NodeKind)) { // Special case: void foo() ^override: jump to the overridden method. if (const auto *CMD = llvm::dyn_cast(D)) { const InheritableAttr *Attr = D->getAttr(); @@ -315,93 +322,56 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, return Result; } -llvm::StringRef wordTouching(llvm::StringRef Code, unsigned Offset) { - unsigned B = Offset, E = Offset; - while (B > 0 && isIdentifierBody(Code[B - 1])) - --B; - while (E < Code.size() && isIdentifierBody(Code[E])) - ++E; - return Code.slice(B, E); +bool tokenSpelledAt(SourceLocation SpellingLoc, const syntax::TokenBuffer &TB) { + auto ExpandedTokens = TB.expandedTokens( + TB.sourceManager().getMacroArgExpandedLocation(SpellingLoc)); + return !ExpandedTokens.empty(); } -bool isLikelyToBeIdentifier(StringRef Word) { - // Word contains underscore. - // This handles things like snake_case and MACRO_CASE. - if (Word.contains('_')) { - return true; - } - // Word contains capital letter other than at beginning. - // This handles things like lowerCamel and UpperCamel. - // The check for also containing a lowercase letter is to rule out - // initialisms like "HTTP". - bool HasLower = Word.find_if(clang::isLowercase) != StringRef::npos; - bool HasUpper = Word.substr(1).find_if(clang::isUppercase) != StringRef::npos; - if (HasLower && HasUpper) { - return true; - } - // FIXME: There are other signals we could listen for. - // Some of these require inspecting the surroundings of the word as well. - // - mid-sentence Capitalization - // - markup like quotes / backticks / brackets / "\p" - // - word has a qualifier (foo::bar) - return false; +llvm::StringRef sourcePrefix(SourceLocation Loc, const SourceManager &SM) { + auto D = SM.getDecomposedLoc(Loc); + bool Invalid = false; + llvm::StringRef Buf = SM.getBufferData(D.first, &Invalid); + if (Invalid || D.second > Buf.size()) + return ""; + return Buf.substr(0, D.second); } -bool tokenSurvivedPreprocessing(SourceLocation Loc, - const syntax::TokenBuffer &TB) { - auto WordExpandedTokens = - TB.expandedTokens(TB.sourceManager().getMacroArgExpandedLocation(Loc)); - return !WordExpandedTokens.empty(); +bool isDependentName(ASTNodeKind NodeKind) { + return NodeKind.isSame(ASTNodeKind::getFromNodeKind()) || + NodeKind.isSame( + ASTNodeKind::getFromNodeKind()) || + NodeKind.isSame( + ASTNodeKind::getFromNodeKind()); } } // namespace std::vector -locateSymbolNamedTextuallyAt(ParsedAST &AST, const SymbolIndex *Index, - SourceLocation Loc, - const std::string &MainFilePath) { - const auto &SM = AST.getSourceManager(); - - // Get the raw word at the specified location. - unsigned Pos; - FileID File; - std::tie(File, Pos) = SM.getDecomposedLoc(Loc); - llvm::StringRef Code = SM.getBufferData(File); - llvm::StringRef Word = wordTouching(Code, Pos); - if (Word.empty()) +locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST, + const SymbolIndex *Index, const std::string &MainFilePath, + ASTNodeKind NodeKind) { + // Don't use heuristics if this is a real identifier, or not an + // identifier. + // Exception: dependent names, because those may have useful textual + // matches that AST-based heuristics cannot find. + if ((Word.ExpandedToken && !isDependentName(NodeKind)) || + !Word.LikelyIdentifier || !Index) return {}; - unsigned WordOffset = Word.data() - Code.data(); - SourceLocation WordStart = SM.getComposedLoc(File, WordOffset); - - // Attempt to determine the kind of token that contains the word, - // and bail if it's a string literal. Note that we cannot always - // determine the token kind (e.g. comments, for which we do want - // to activate, are not retained by TokenBuffer). - for (syntax::Token T : - syntax::spelledTokensTouching(WordStart, AST.getTokens())) { - if (T.range(AST.getSourceManager()).touches(WordOffset + Word.size())) { - if (isStringLiteral(T.kind())) - return {}; - } - } - - // Do not consider tokens that survived preprocessing. - // We are erring on the safe side here, as a user may expect to get - // accurate (as opposed to textual-heuristic) results for such tokens. - // FIXME: Relax this for dependent code. - if (tokenSurvivedPreprocessing(WordStart, AST.getTokens())) - return {}; - - // Additionally filter for signals that the word is likely to be an - // identifier. This avoids triggering on e.g. random words in a comment. - if (!isLikelyToBeIdentifier(Word)) + // We don't want to handle words in string literals. It'd be nice to whitelist + // comments instead, but they're not retained in TokenBuffer. + if (Word.PartOfSpelledToken && + isStringLiteral(Word.PartOfSpelledToken->kind())) return {}; + const auto &SM = AST.getSourceManager(); // Look up the selected word in the index. FuzzyFindRequest Req; - Req.Query = Word.str(); + Req.Query = Word.Text.str(); Req.ProximityPaths = {MainFilePath}; - Req.Scopes = visibleNamespaces(Code.take_front(Pos), AST.getLangOpts()); + // Find the namespaces to query by lexing the file. + Req.Scopes = + visibleNamespaces(sourcePrefix(Word.Location, SM), AST.getLangOpts()); // FIXME: For extra strictness, consider AnyScope=false. Req.AnyScope = true; // We limit the results to 3 further below. This limit is to avoid fetching @@ -416,7 +386,7 @@ locateSymbolNamedTextuallyAt(ParsedAST &AST, const SymbolIndex *Index, // This is to avoid too many false positives. // We could relax this in the future (e.g. to allow for typos) if we make // the query more accurate by other means. - if (Sym.Name != Word) + if (Sym.Name != Word.Text) return; // Exclude constructor results. They have the same name as the class, @@ -481,6 +451,82 @@ locateSymbolNamedTextuallyAt(ParsedAST &AST, const SymbolIndex *Index, return Results; } +const syntax::Token *findNearbyIdentifier(const SpelledWord &Word, + const syntax::TokenBuffer &TB) { + // Don't use heuristics if this is a real identifier. + // Unlikely identifiers are OK if they were used as identifiers nearby. + if (Word.ExpandedToken) + return nullptr; + // We don't want to handle words in string literals. It'd be nice to whitelist + // comments instead, but they're not retained in TokenBuffer. + if (Word.PartOfSpelledToken && + isStringLiteral(Word.PartOfSpelledToken->kind())) + return {}; + + const SourceManager &SM = TB.sourceManager(); + // We prefer the closest possible token, line-wise. Backwards is penalized. + // Ties are implicitly broken by traversal order (first-one-wins). + auto File = SM.getFileID(Word.Location); + unsigned WordLine = SM.getSpellingLineNumber(Word.Location); + auto Cost = [&](SourceLocation Loc) -> unsigned { + assert(SM.getFileID(Loc) == File && "spelled token in wrong file?"); + unsigned Line = SM.getSpellingLineNumber(Loc); + if (Line > WordLine) + return 1 + llvm::Log2_64(Line - WordLine); + if (Line < WordLine) + return 2 + llvm::Log2_64(WordLine - Line); + return 0; + }; + const syntax::Token *BestTok = nullptr; + // Search bounds are based on word length: 2^N lines forward. + unsigned BestCost = Word.Text.size() + 1; + + // Updates BestTok and BestCost if Tok is a good candidate. + // May return true if the cost is too high for this token. + auto Consider = [&](const syntax::Token &Tok) { + if (!(Tok.kind() == tok::identifier && Tok.text(SM) == Word.Text)) + return false; + // No point guessing the same location we started with. + if (Tok.location() == Word.Location) + return false; + // We've done cheap checks, compute cost so we can break the caller's loop. + unsigned TokCost = Cost(Tok.location()); + if (TokCost >= BestCost) + return true; // causes the outer loop to break. + // Allow locations that might be part of the AST, and macros (even if empty) + // but not things like disabled preprocessor sections. + if (!(tokenSpelledAt(Tok.location(), TB) || TB.expansionStartingAt(&Tok))) + return false; + // We already verified this token is an improvement. + BestCost = TokCost; + BestTok = &Tok; + return false; + }; + auto SpelledTokens = TB.spelledTokens(File); + // Find where the word occurred in the token stream, to search forward & back. + auto *I = llvm::partition_point(SpelledTokens, [&](const syntax::Token &T) { + assert(SM.getFileID(T.location()) == SM.getFileID(Word.Location)); + return T.location() >= Word.Location; // Comparison OK: same file. + }); + // Search for matches after the cursor. + for (const syntax::Token &Tok : llvm::makeArrayRef(I, SpelledTokens.end())) + if (Consider(Tok)) + break; // costs of later tokens are greater... + // Search for matches before the cursor. + for (const syntax::Token &Tok : + llvm::reverse(llvm::makeArrayRef(SpelledTokens.begin(), I))) + if (Consider(Tok)) + break; + + if (BestTok) + vlog( + "Word {0} under cursor {1} isn't a token (after PP), trying nearby {2}", + Word.Text, Word.Location.printToString(SM), + BestTok->location().printToString(SM)); + + return BestTok; +} + std::vector locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index) { const auto &SM = AST.getSourceManager(); @@ -511,12 +557,35 @@ std::vector locateSymbolAt(ParsedAST &AST, Position Pos, // expansion.) return {*std::move(Macro)}; - auto ASTResults = - locateASTReferent(*CurLoc, TouchedIdentifier, AST, *MainFilePath, Index); + ASTNodeKind NodeKind; + auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST, + *MainFilePath, Index, &NodeKind); if (!ASTResults.empty()) return ASTResults; - return locateSymbolNamedTextuallyAt(AST, Index, *CurLoc, *MainFilePath); + // If the cursor can't be resolved directly, try fallback strategies. + auto Word = + SpelledWord::touching(*CurLoc, AST.getTokens(), AST.getLangOpts()); + if (Word) { + // Is the same word nearby a real identifier that might refer to something? + if (const syntax::Token *NearbyIdent = + findNearbyIdentifier(*Word, AST.getTokens())) { + if (auto Macro = locateMacroReferent(*NearbyIdent, AST, *MainFilePath)) + return {*std::move(Macro)}; + ASTResults = + locateASTReferent(NearbyIdent->location(), NearbyIdent, AST, + *MainFilePath, Index, /*NodeKind=*/nullptr); + if (!ASTResults.empty()) + return ASTResults; + } + // No nearby word, or it didn't refer to anything either. Try the index. + auto TextualResults = + locateSymbolTextually(*Word, AST, Index, *MainFilePath, NodeKind); + if (!TextualResults.empty()) + return TextualResults; + } + + return {}; } std::vector getDocumentLinks(ParsedAST &AST) { diff --git a/clang-tools-extra/clangd/XRefs.h b/clang-tools-extra/clangd/XRefs.h index 8f42ca8d3265d3c56fd5e23f77ea9adbcc090b6f..d1ba7bac66600c2e5f73b834b145f4334df38469 100644 --- a/clang-tools-extra/clangd/XRefs.h +++ b/clang-tools-extra/clangd/XRefs.h @@ -14,10 +14,12 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H #include "FormattedString.h" -#include "Path.h" #include "Protocol.h" +#include "SourceCode.h" #include "index/Index.h" #include "index/SymbolLocation.h" +#include "support/Path.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Type.h" #include "clang/Format/Format.h" #include "clang/Index/IndexSymbol.h" @@ -26,6 +28,10 @@ #include namespace clang { +namespace syntax { +class Token; +class TokenBuffer; +} // namespace syntax namespace clangd { class ParsedAST; @@ -49,20 +55,22 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &, const LocatedSymbol &); std::vector locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index = nullptr); -// Tries to provide a textual fallback for locating a symbol referenced at -// a location, by looking up the word under the cursor as a symbol name in the -// index. The aim is to pick up references to symbols in contexts where +// Tries to provide a textual fallback for locating a symbol by looking up the +// word under the cursor as a symbol name in the index. +// The aim is to pick up references to symbols in contexts where // AST-based resolution does not work, such as comments, strings, and PP -// disabled regions. The implementation takes a number of measures to avoid -// false positives, such as looking for some signal that the word at the -// given location is likely to be an identifier. The function does not -// currently return results for locations that end up as real expanded -// tokens, although this may be relaxed for e.g. dependent code in the future. +// disabled regions. // (This is for internal use by locateSymbolAt, and is exposed for testing). std::vector -locateSymbolNamedTextuallyAt(ParsedAST &AST, const SymbolIndex *Index, - SourceLocation Loc, - const std::string &MainFilePath); +locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST, + const SymbolIndex *Index, const std::string &MainFilePath, + ASTNodeKind NodeKind); + +// Try to find a proximate occurrence of `Word` as an identifier, which can be +// used to resolve it. +// (This is for internal use by locateSymbolAt, and is exposed for testing). +const syntax::Token *findNearbyIdentifier(const SpelledWord &Word, + const syntax::TokenBuffer &TB); /// Get all document links std::vector getDocumentLinks(ParsedAST &AST); diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore b/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore deleted file mode 100644 index a73617e32b4b25ee9a8487b7525442bb1ce23950..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -out -node_modules -.vscode-test diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json b/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json deleted file mode 100644 index 7d414bc00f32eca0832fc52ab445a5ce7085a13e..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json +++ /dev/null @@ -1,28 +0,0 @@ -// A launch configuration that compiles extension and opens it inside a new window. -{ - "version": "0.1.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], - "preLaunchTask": "npm" - }, - { - "name": "Launch Tests", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ], - "preLaunchTask": "npm" - } - ] -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json b/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json deleted file mode 100644 index d13713339847f5bdaa936a0e5082c1ef2b4403c3..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "out": true // set this to false to include "out" folder in search results - } -} \ No newline at end of file diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json b/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json deleted file mode 100644 index 65b1c9598c0e128cafabc701fc2a21ac0ddd1040..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json +++ /dev/null @@ -1,32 +0,0 @@ -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -// Task runner calls custom npm script to compile the extension. -{ - "version": "2.0.0", - - // Run NPM. - "command": "npm", - - // This command is a shell script. - "type": "shell", - - // show the output window only if unrecognized errors occur. - "presentation": { - "reveal": "silent", - }, - - // Run custom "compile" script as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // tsc compiler is kept alive and runs in the background. - "isBackground": true, - - // Find compilation problems in the output through tsc in watch mode. - "problemMatcher": "$tsc-watch" -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore b/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore deleted file mode 100644 index 5ff3c19320f69ed4f82eb5a6da47e8187fefea38..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore +++ /dev/null @@ -1,9 +0,0 @@ -.vscode/** -.vscode-test/** -out/test/** -test/** -src/** -**/*.map -.gitignore -tsconfig.json -vsc-extension-quickstart.md diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/DEVELOPING.md b/clang-tools-extra/clangd/clients/clangd-vscode/DEVELOPING.md deleted file mode 100644 index 15f2b930329e9539259b99b782faad53d8d6fe73..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/DEVELOPING.md +++ /dev/null @@ -1,53 +0,0 @@ -# Development - -A guide of developing `vscode-clangd` extension. - -## Requirements - -* VS Code -* node.js and npm - -## Steps - -1. Make sure you disable the installed `vscode-clangd` extension in VS Code. -2. Make sure you have clangd in `/usr/bin/clangd` or edit `src/extension.ts` to -point to the binary. -3. To start a development instance of VS code extended with this, run: - -```bash - $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/ - $ npm install - $ code . - # When VSCode starts, press . -``` - -# Contributing - -Please follow the existing code style when contributing to the extension, we -recommend to run `npm run format` before sending a patch. - -# Publish to VS Code Marketplace - -New changes to `clangd-vscode` are not released until a new version is published -to the marketplace. - -## Requirements - -* Make sure install the `vsce` command (`npm install -g vsce`) -* `llvm-vs-code-extensions` account -* Bump the version in `package.json`, and commit the change to upstream - -The extension is published under `llvm-vs-code-extensions` account, which is -maintained by clangd developers. If you want to make a new release, please -contact clangd-dev@lists.llvm.org. - -## Steps - -```bash - $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/ - # For the first time, you need to login into the account. vsce will ask you - for the Personal Access Token and will remember it for future commands. - $ vsce login llvm-vs-code-extensions - # Publish the extension to the VSCode marketplace. - $ npm run publish -``` diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE b/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE deleted file mode 100644 index 6a18483d5b384a9b7c9a57b4c6abab15c59f05f9..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2019 The LLVM Developers - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/README.md b/clang-tools-extra/clangd/clients/clangd-vscode/README.md deleted file mode 100644 index 44b7f9697e78fec53639c19160eebe1878c13ff4..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/README.md +++ /dev/null @@ -1,103 +0,0 @@ -# vscode-clangd - -Provides C/C++ language IDE features for VS Code using [clangd](https://clang.llvm.org/extra/clangd.html): - - - code completion - - compile errors and warnings - - go-to-definition and cross references - - include management - - code formatting - - simple refactorings - -## Setup - -### `clangd` server - -`clangd` is a language server that must be installed separately, see -[getting started](https://clang.llvm.org/extra/clangd/Installation.html#installing-clangd). -The vscode-clangd extension will look for `clangd` on your PATH (you can change -this in the settings). - -### Project setup - -clangd is based on the clang C++ compiler, and understands even complex C++ -code. However, you must tell clangd how your project is built (compile flags). -[A `compile_commands.json` file](http://clang.llvm.org/docs/JSONCompilationDatabase.html) -can usually be generated by your build system -(e.g. by setting `-DCMAKE_EXPORT_COMPILE_COMMANDS=1` when building with CMake, -or with -[many other tools](https://sarcasm.github.io/notes/dev/compilation-database.html)). - -It should live at the top of your source tree: symlink or copy it there. - -## Features - -### Code completion - -Suggestions will appear as you type names, or after `.` or `->`. -Because clangd uses a full C++ parser, code completion has access to precise -type information. - -![Code completion](doc-assets/complete.png) - -### Errors, warnings, and clang-tidy - -Code errors are shown as you type (both as red squiggle underlines, and in the -"Problems" panel). These are the same as produced by the clang compiler, and -suggested fixes can automatically be applied. - -![Error with fix](doc-assets/diagnostics.png) - -Most clang-tidy checks are supported (these can be enabled using a [.clang-tidy -file](https://clang.llvm.org/extra/clang-tidy/)). - -### Cross-references - -Go-to-definition and find-references work across your code, using a project-wide -index. - -![Cross-reference list](doc-assets/xrefs.png) - -Press `Ctrl-P #` to quickly navigate to a symbol by name. - -### Include management - -Code completion works across your codebase and adds `#include` directives where -needed. The `•` shows includes that will be inserted. - -clangd can also suggest inserting missing #includes, where they cause errors. - -![Fix inserts include](doc-assets/include.png) - -### Formatting - -clangd uses the `clang-format` engine. You can format a file or the selection. -When "Format on Type" is enabled in the settings, pressing enter will cause -clangd to format the old line and semantically reindent. - -![Format-on-type](doc-assets/format.png) - -The style used for formatting (and certain other operations) is controlled by -the .clang-format file is controlled by the project's -[.clang-format file](https://clang.llvm.org/docs/ClangFormatStyleOptions.html). - -### Refactoring - -clangd supports some local refactorings. When you select an expression or -declaration, the lightbulb menu appears and you can choose a code action. - -![Extract variable code action](doc-assets/extract.png) - -Current refactorings include: - - extract variable/function - - expand `auto` types and macros - - use raw strings - - rename (bound to ``, rather than a contextual code action) - -## Bugs/contributing - -clangd and vscode-clangd are part of the [LLVM project](https://llvm.org). - -If you'd like to help out, reach out to clangd-dev@lists.llvm.org. - -If you've found a bug, please file at https://github.com/clangd/clangd/issues. diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/complete.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/complete.png deleted file mode 100644 index 1ce9e82c64c36e2d782f9d636c4594566b3f9843..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/complete.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/diagnostics.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/diagnostics.png deleted file mode 100644 index 2ca335be59f897dbacd04f4bea016bc1ab08d76f..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/diagnostics.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/extract.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/extract.png deleted file mode 100644 index d62aeebadbdebdeea9080241ad4ece33ef924913..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/extract.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/format.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/format.png deleted file mode 100644 index b68d37e9cbfe07b88ac972f007b4e18723aea792..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/format.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/include.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/include.png deleted file mode 100644 index 8909fd79e91df5dc4aff58c876793f3eb4bb13b2..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/include.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/symbolsearch.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/symbolsearch.png deleted file mode 100644 index cce137a8aa15a872bd22a0f2c7542511a9e6fa77..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/symbolsearch.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/xrefs.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/xrefs.png deleted file mode 100644 index 622eb690dd1bca51d41d3c0da13937958e602dc7..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/xrefs.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/icon.png b/clang-tools-extra/clangd/clients/clangd-vscode/icon.png deleted file mode 100644 index 3c32cc045f2b4c968afbbcaa23cdd81082000434..0000000000000000000000000000000000000000 Binary files a/clang-tools-extra/clangd/clients/clangd-vscode/icon.png and /dev/null differ diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json b/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json deleted file mode 100644 index 67f4cfb77bc3b8d65650913de56c8ee506c9e834..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json +++ /dev/null @@ -1,419 +0,0 @@ -{ - "name": "vscode-clangd", - "version": "0.0.21", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "2.2.48", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", - "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==", - "dev": true - }, - "@types/node": { - "version": "6.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.9.tgz", - "integrity": "sha512-leP/gxHunuazPdZaCvsCefPQxinqUDsCxCR5xaDUrY2MkYxQRFZZwU5e7GojyYsGB7QVtCi7iVEl/hoFXQYc+w==", - "dev": true - }, - "@types/vscode": { - "version": "1.41.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.41.0.tgz", - "integrity": "sha512-7SfeY5u9jgiELwxyLB3z7l6l/GbN9CqpCQGkcRlB7tKRFBxzbz2PoBfGrLxI1vRfUCIq5+hg5vtDHExwq5j3+A==", - "dev": true - }, - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "clang-format": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.2.4.tgz", - "integrity": "sha512-sw+nrGUp3hvmANd1qF8vZPuezSYQAiXgGBiEtkXTtJnnu6b00fCqkkDIsnRKrNgg4nv6NYZE92ejvOMIXZoejw==", - "dev": true, - "requires": { - "async": "^1.5.2", - "glob": "^7.0.0", - "resolve": "^1.1.6" - } - }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "jsonc-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.0.tgz", - "integrity": "sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA==" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - }, - "dependencies": { - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - } - } - }, - "typescript": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", - "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", - "dev": true - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageclient": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.0.tgz", - "integrity": "sha512-Tcp0VoOaa0YzxL4nEfK9tsmcy76Eo8jNLvFQZwh2c8oMm02luL8uGYPLQNAiZ3XGgegfcwiQFZMqbW7DNV0vxA==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.2" - } - }, - "vscode-languageserver": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.0.tgz", - "integrity": "sha512-Q5kUJegYclTZMnKUaEcxJK41Ozp6qJhhoFJYj0w8y8j9JXdKT479LE945QCKRvSgWfsqTSUmgsozVTUIwQQxHw==", - "requires": { - "vscode-languageserver-protocol": "^3.15.2" - } - }, - "vscode-languageserver-protocol": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.2.tgz", - "integrity": "sha512-GdL05JKOgZ76RDg3suiGCl9enESM7iQgGw4x93ibTh4sldvZmakHmTeZ4iUApPPGKf6O3OVBtrsksBXnHYaxNg==", - "requires": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "vscode-test": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.3.0.tgz", - "integrity": "sha512-LddukcBiSU2FVTDr3c1D8lwkiOvwlJdDL2hqVbn6gIz+rpTqUCkMZSKYm94Y1v0WXlHSDQBsXyY+tchWQgGVsw==", - "dev": true, - "requires": { - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.4", - "rimraf": "^2.6.3" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - } - } -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/package.json b/clang-tools-extra/clangd/clients/clangd-vscode/package.json deleted file mode 100644 index 99ee119ea57da7591c3121af29ea0cd18c306547..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/package.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "name": "vscode-clangd", - "displayName": "vscode-clangd", - "description": "Clang Language Server", - "version": "0.0.22", - "publisher": "llvm-vs-code-extensions", - "homepage": "https://clangd.llvm.org/", - "icon": "icon.png", - "engines": { - "vscode": "^1.41.0" - }, - "categories": [ - "Programming Languages", - "Linters", - "Snippets" - ], - "keywords": [ - "C", - "C++", - "LSP", - "Clangd", - "LLVM" - ], - "activationEvents": [ - "onLanguage:c", - "onLanguage:cpp", - "onLanguage:cuda", - "onLanguage:objective-c", - "onLanguage:objective-cpp", - "onCommand:clangd-vscode.activate" - ], - "main": "./out/src/extension", - "scripts": { - "vscode:prepublish": "tsc -p ./", - "compile": "tsc -watch -p ./", - "format": "clang-format --style=LLVM -i --glob=\"{src,test}/*.ts\"", - "test": "tsc -p ./ && node ./out/test/runTest.js", - "package": "vsce package --baseImagesUrl https://raw.githubusercontent.com/llvm/llvm-project/master/clang-tools-extra/clangd/clients/clangd-vscode/", - "publish": "vsce publish --baseImagesUrl https://raw.githubusercontent.com/llvm/llvm-project/master/clang-tools-extra/clangd/clients/clangd-vscode/" - }, - "dependencies": { - "jsonc-parser": "^2.1.0", - "vscode-languageclient": "^6.1.0", - "vscode-languageserver": "^6.1.0", - "vscode-languageserver-types": "^3.15.1" - }, - "devDependencies": { - "@types/glob": "^7.1.1", - "@types/mocha": "^2.2.32", - "@types/node": "^6.0.40", - "@types/vscode": "^1.41.0", - "glob": "^7.1.4", - "clang-format": "1.2.4", - "mocha": "^5.2.0", - "typescript": "^3.5.1", - "vscode-test": "^1.3.0" - }, - "repository": { - "type": "git", - "url": "https://github.com/llvm/llvm-project.git", - "directory": "clang-tools/extra/clangd/clients/clangd-vscode" - }, - "contributes": { - "languages": [ - { - "id": "cpp", - "filenamePatterns": [ - "**/include/c++/**", - "**/MSVC/*/include/**" - ], - "firstLine": "^/[/*].*-\\*-\\s*C\\+\\+\\s*-\\*-.*" - }, - { - "id": "cuda", - "extensions": [ - ".cu", - ".cuh" - ] - } - ], - "configuration": { - "type": "object", - "title": "clangd configuration", - "properties": { - "clangd.path": { - "type": "string", - "default": "clangd", - "description": "The path to clangd executable, e.g.: /usr/bin/clangd" - }, - "clangd.arguments": { - "type": "array", - "default": [], - "items": { - "type": "string" - }, - "description": "Arguments for clangd server" - }, - "clangd.syncFileEvents": { - "type": "boolean", - "default": true, - "description": "Whether or not to send file events to clangd (File created, changed or deleted). This can be disabled for performance consideration." - }, - "clangd.trace": { - "type": "string", - "description": "Names a file that clangd should log a performance trace to, in chrome trace-viewer JSON format." - }, - "clangd.semanticHighlighting": { - "type": "boolean", - "default": "true", - "description": "Enable semantic highlighting in clangd" - } - } - }, - "commands": [ - { - "command": "clangd-vscode.switchheadersource", - "title": "Switch between Source/Header" - }, - { - "command": "clangd-vscode.activate", - "title": "Manually activate clangd extension" - } - ], - "keybindings": [ - { - "command": "clangd-vscode.switchheadersource", - "key": "Alt+o", - "mac": "Alt+cmd+o", - "when": "editorTextFocus" - } - ] - } -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts b/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts deleted file mode 100644 index a7570b63e552e5801a19f89710e7c05bda6456f6..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts +++ /dev/null @@ -1,190 +0,0 @@ -import * as vscode from 'vscode'; -import * as vscodelc from 'vscode-languageclient'; -import * as semanticHighlighting from './semantic-highlighting'; - -/** - * Get an option from workspace configuration. - * @param option name of the option (e.g. for clangd.path should be path) - * @param defaultValue default value to return if option is not set - */ -function getConfig(option: string, defaultValue?: any): T { - const config = vscode.workspace.getConfiguration('clangd'); - return config.get(option, defaultValue); -} - -namespace SwitchSourceHeaderRequest { -export const type = - new vscodelc.RequestType('textDocument/switchSourceHeader'); -} - -class FileStatus { - private statuses = new Map(); - private readonly statusBarItem = - vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 10); - - onFileUpdated(fileStatus: any) { - const filePath = vscode.Uri.parse(fileStatus.uri); - this.statuses.set(filePath.fsPath, fileStatus); - this.updateStatus(); - } - - updateStatus() { - const path = vscode.window.activeTextEditor.document.fileName; - const status = this.statuses.get(path); - if (!status) { - this.statusBarItem.hide(); - return; - } - this.statusBarItem.text = `clangd: ` + status.state; - this.statusBarItem.show(); - } - - clear() { - this.statuses.clear(); - this.statusBarItem.hide(); - } - - dispose() { this.statusBarItem.dispose(); } -} - -class ClangdLanguageClient extends vscodelc.LanguageClient { - // Override the default implementation for failed requests. The default - // behavior is just to log failures in the output panel, however output panel - // is designed for extension debugging purpose, normal users will not open it, - // thus when the failure occurs, normal users doesn't know that. - // - // For user-interactive operations (e.g. applyFixIt, applyTweaks), we will - // prompt up the failure to users. - logFailedRequest(rpcReply: vscodelc.RPCMessageType, error: any) { - if (error instanceof vscodelc.ResponseError && - rpcReply.method === "workspace/executeCommand") - vscode.window.showErrorMessage(error.message); - // Call default implementation. - super.logFailedRequest(rpcReply, error); - } -} - -class EnableEditsNearCursorFeature implements vscodelc.StaticFeature { - initialize() {} - fillClientCapabilities(capabilities: vscodelc.ClientCapabilities): void { - const extendedCompletionCapabilities: any = - capabilities.textDocument.completion; - extendedCompletionCapabilities.editsNearCursor = true; - } -} - -/** - * This method is called when the extension is activated. The extension is - * activated the very first time a command is executed. - */ -export function activate(context: vscode.ExtensionContext) { - const syncFileEvents = getConfig('syncFileEvents', true); - - const clangd: vscodelc.Executable = { - command : getConfig('path'), - args : getConfig('arguments') - }; - const traceFile = getConfig('trace'); - if (!!traceFile) { - const trace = {CLANGD_TRACE : traceFile}; - clangd.options = {env : {...process.env, ...trace}}; - } - const serverOptions: vscodelc.ServerOptions = clangd; - - const clientOptions: vscodelc.LanguageClientOptions = { - // Register the server for c-family and cuda files. - documentSelector: [ - { scheme: 'file', language: 'c' }, - { scheme: 'file', language: 'cpp' }, - // CUDA is not supported by vscode, but our extension does supports it. - { scheme: 'file', language: 'cuda' }, - { scheme: 'file', language: 'objective-c'}, - { scheme: 'file', language: 'objective-cpp'} - ], - synchronize: !syncFileEvents ? undefined : { - // FIXME: send sync file events when clangd provides implementations. - }, - initializationOptions: { clangdFileStatus: true }, - // Do not switch to output window when clangd returns output. - revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never, - - // We hack up the completion items a bit to prevent VSCode from re-ranking them - // and throwing away all our delicious signals like type information. - // - // VSCode sorts by (fuzzymatch(prefix, item.filterText), item.sortText) - // By adding the prefix to the beginning of the filterText, we get a perfect - // fuzzymatch score for every item. - // The sortText (which reflects clangd ranking) breaks the tie. - // This also prevents VSCode from filtering out any results due to the - // differences in how fuzzy filtering is applies, e.g. enable dot-to-arrow - // fixes in completion. - // - // We also have to mark the list as incomplete to force retrieving new rankings. - // See https://github.com/microsoft/language-server-protocol/issues/898 - middleware: { - provideCompletionItem: async (document, position, context, token, next) => { - let list = await next(document, position, context, token); - let items = (Array.isArray(list) ? list : list.items).map(item => { - // Gets the prefix used by VSCode when doing fuzzymatch. - let prefix = document.getText(new vscode.Range(item.range.start, position)) - if (prefix) - item.filterText = prefix + "_" + item.filterText; - return item; - }) - return new vscode.CompletionList(items, /*isIncomplete=*/true); - } - }, - }; - - const clangdClient = new ClangdLanguageClient('Clang Language Server', - serverOptions, clientOptions); - if (getConfig('semanticHighlighting')) { - const semanticHighlightingFeature = - new semanticHighlighting.SemanticHighlightingFeature(clangdClient, - context); - context.subscriptions.push( - vscode.Disposable.from(semanticHighlightingFeature)); - clangdClient.registerFeature(semanticHighlightingFeature); - } - clangdClient.registerFeature(new EnableEditsNearCursorFeature); - console.log('Clang Language Server is now active!'); - context.subscriptions.push(clangdClient.start()); - context.subscriptions.push(vscode.commands.registerCommand( - 'clangd-vscode.switchheadersource', async () => { - const uri = - vscode.Uri.file(vscode.window.activeTextEditor.document.fileName); - if (!uri) { - return; - } - const docIdentifier = - vscodelc.TextDocumentIdentifier.create(uri.toString()); - const sourceUri = await clangdClient.sendRequest( - SwitchSourceHeaderRequest.type, docIdentifier); - if (!sourceUri) { - return; - } - const doc = await vscode.workspace.openTextDocument( - vscode.Uri.parse(sourceUri)); - vscode.window.showTextDocument(doc); - })); - const status = new FileStatus(); - context.subscriptions.push(vscode.Disposable.from(status)); - context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor( - () => { status.updateStatus(); })); - context.subscriptions.push(clangdClient.onDidChangeState(({newState}) => { - if (newState == vscodelc.State.Running) { - // clangd starts or restarts after crash. - clangdClient.onNotification( - 'textDocument/clangd.fileStatus', - (fileStatus) => { status.onFileUpdated(fileStatus); }); - } else if (newState == vscodelc.State.Stopped) { - // Clear all cached statuses when clangd crashes. - status.clear(); - } - })); - // An empty place holder for the activate command, otherwise we'll get an - // "command is not registered" error. - context.subscriptions.push(vscode.commands.registerCommand( - 'clangd-vscode.activate', async () => {})); -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts b/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts deleted file mode 100644 index 17517441bab9ede621cc0438a968a223eeb2cb39..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts +++ /dev/null @@ -1,399 +0,0 @@ -import * as fs from 'fs'; -import * as jsonc from "jsonc-parser"; -import * as path from 'path'; -import * as vscode from 'vscode'; -import * as vscodelc from 'vscode-languageclient'; -import * as vscodelct from 'vscode-languageserver-types'; - -// Parameters for the semantic highlighting (server-side) push notification. -// Mirrors the structure in the semantic highlighting proposal for LSP. -interface SemanticHighlightingParams { - // The text document that has to be decorated with the semantic highlighting - // information. - textDocument: vscodelct.VersionedTextDocumentIdentifier; - // An array of semantic highlighting information. - lines: SemanticHighlightingInformation[]; -} -// Contains the highlighting information for a specified line. Mirrors the -// structure in the semantic highlighting proposal for LSP. -interface SemanticHighlightingInformation { - // The zero-based line position in the text document. - line: number; - // A base64 encoded string representing every single highlighted characters - // with its start position, length and the "lookup table" index of of the - // semantic highlighting Text Mate scopes. - tokens?: string; -} - -// A SemanticHighlightingToken decoded from the base64 data sent by clangd. -interface SemanticHighlightingToken { - // Start column for this token. - character: number; - // Length of the token. - length: number; - // The TextMate scope index to the clangd scope lookup table. - scopeIndex: number; -} -// A line of decoded highlightings from the data clangd sent. -export interface SemanticHighlightingLine { - // The zero-based line position in the text document. - line: number; - // All SemanticHighlightingTokens on the line. - tokens: SemanticHighlightingToken[]; -} - -// Language server push notification providing the semantic highlighting -// information for a text document. -const NotificationType = - new vscodelc.NotificationType( - 'textDocument/semanticHighlighting'); - -// The feature that should be registered in the vscode lsp for enabling -// experimental semantic highlighting. -export class SemanticHighlightingFeature implements vscodelc.StaticFeature { - // The TextMate scope lookup table. A token with scope index i has the scopes - // on index i in the lookup table. - scopeLookupTable: string[][]; - // The object that applies the highlightings clangd sends. - highlighter: Highlighter; - // Any disposables that should be cleaned up when clangd crashes. - private subscriptions: vscode.Disposable[] = []; - constructor(client: vscodelc.BaseLanguageClient, - context: vscode.ExtensionContext) { - context.subscriptions.push(client.onDidChangeState(({newState}) => { - if (newState == vscodelc.State.Running) { - // Register handler for semantic highlighting notification. - client.onNotification(NotificationType, - this.handleNotification.bind(this)); - } else if (newState == vscodelc.State.Stopped) { - // Dispose resources when clangd crashes. - this.dispose(); - } - })); - } - fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) { - // Extend the ClientCapabilities type and add semantic highlighting - // capability to the object. - const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities& - {semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} = - capabilities.textDocument; - textDocumentCapabilities.semanticHighlightingCapabilities = { - semanticHighlighting : true, - }; - } - - async loadCurrentTheme() { - const themeRuleMatcher = new ThemeRuleMatcher( - await loadTheme(vscode.workspace.getConfiguration('workbench') - .get('colorTheme'))); - this.highlighter.initialize(themeRuleMatcher); - } - - initialize(capabilities: vscodelc.ServerCapabilities, - documentSelector: vscodelc.DocumentSelector|undefined) { - // The semantic highlighting capability information is in the capabilities - // object but to access the data we must first extend the ServerCapabilities - // type. - const serverCapabilities: vscodelc.ServerCapabilities& - {semanticHighlighting?: {scopes : string[][]}} = capabilities; - if (!serverCapabilities.semanticHighlighting) - return; - this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes; - // Important that highlighter is created before the theme is loading as - // otherwise it could try to update the themeRuleMatcher without the - // highlighter being created. - this.highlighter = new Highlighter(this.scopeLookupTable); - this.subscriptions.push(vscode.Disposable.from(this.highlighter)); - // Adds a listener to reload the theme when it changes. - this.subscriptions.push( - vscode.workspace.onDidChangeConfiguration((conf) => { - if (!conf.affectsConfiguration('workbench.colorTheme')) - return; - this.loadCurrentTheme(); - })); - this.loadCurrentTheme(); - // Event handling for handling with TextDocuments/Editors lifetimes. - this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors( - (editors: vscode.TextEditor[]) => editors.forEach( - (e) => this.highlighter.applyHighlights(e.document.uri)))); - this.subscriptions.push(vscode.workspace.onDidCloseTextDocument( - (doc) => this.highlighter.removeFileHighlightings(doc.uri))); - } - - handleNotification(params: SemanticHighlightingParams) { - const lines: SemanticHighlightingLine[] = params.lines.map( - (line) => ({line : line.line, tokens : decodeTokens(line.tokens)})); - this.highlighter.highlight(vscode.Uri.parse(params.textDocument.uri), - lines); - } - // Disposes of all disposable resources used by this object. - public dispose() { - this.subscriptions.forEach((d) => d.dispose()); - this.subscriptions = []; - } -} - -// Converts a string of base64 encoded tokens into the corresponding array of -// HighlightingTokens. -export function decodeTokens(tokens: string): SemanticHighlightingToken[] { - const scopeMask = 0xFFFF; - const lenShift = 0x10; - const uint32Size = 4; - const buf = Buffer.from(tokens, 'base64'); - const retTokens = []; - for (let i = 0, end = buf.length / uint32Size; i < end; i += 2) { - const start = buf.readUInt32BE(i * uint32Size); - const lenKind = buf.readUInt32BE((i + 1) * uint32Size); - const scopeIndex = lenKind & scopeMask; - const len = lenKind >>> lenShift; - retTokens.push({character : start, scopeIndex : scopeIndex, length : len}); - } - - return retTokens; -} - -// The main class responsible for processing of highlightings that clangd -// sends. -export class Highlighter { - // Maps uris with currently open TextDocuments to the current highlightings. - private files: Map> = new Map(); - // DecorationTypes for the current theme that are used when highlighting. A - // SemanticHighlightingToken with scopeIndex i should have the decoration at - // index i in this list. - private decorationTypes: vscode.TextEditorDecorationType[] = []; - // The clangd TextMate scope lookup table. - private scopeLookupTable: string[][]; - constructor(scopeLookupTable: string[][]) { - this.scopeLookupTable = scopeLookupTable; - } - public dispose() { - this.files.clear(); - this.decorationTypes.forEach((t) => t.dispose()); - // Dispose must not be not called multiple times if initialize is - // called again. - this.decorationTypes = []; - } - // This function must be called at least once or no highlightings will be - // done. Sets the theme that is used when highlighting. Also triggers a - // recolorization for all current highlighters. Should be called whenever the - // theme changes and has been loaded. Should also be called when the first - // theme is loaded. - public initialize(themeRuleMatcher: ThemeRuleMatcher) { - this.decorationTypes.forEach((t) => t.dispose()); - this.decorationTypes = this.scopeLookupTable.map((scopes) => { - const options: vscode.DecorationRenderOptions = { - // If there exists no rule for this scope the matcher returns an empty - // color. That's ok because vscode does not do anything when applying - // empty decorations. - color : themeRuleMatcher.getBestThemeRule(scopes[0]).foreground, - // If the rangeBehavior is set to Open in any direction the - // highlighting becomes weird in certain cases. - rangeBehavior : vscode.DecorationRangeBehavior.ClosedClosed, - }; - return vscode.window.createTextEditorDecorationType(options); - }); - this.getVisibleTextEditorUris().forEach((fileUri) => - this.applyHighlights(fileUri)); - } - - // Adds incremental highlightings to the current highlightings for the file - // with fileUri. Also applies the highlightings to any associated - // TextEditor(s). - public highlight(fileUri: vscode.Uri, - highlightingLines: SemanticHighlightingLine[]) { - const fileUriStr = fileUri.toString(); - if (!this.files.has(fileUriStr)) { - this.files.set(fileUriStr, new Map()); - } - const fileHighlightings = this.files.get(fileUriStr); - highlightingLines.forEach((line) => fileHighlightings.set(line.line, line)); - this.applyHighlights(fileUri); - } - - // Applies all the highlightings currently stored for a file with fileUri. - public applyHighlights(fileUri: vscode.Uri) { - const fileUriStr = fileUri.toString(); - if (!this.files.has(fileUriStr)) - // There are no highlightings for this file, must return early or will get - // out of bounds when applying the decorations below. - return; - if (!this.decorationTypes.length) - // Can't apply any decorations when there is no theme loaded. - return; - // This must always do a full re-highlighting due to the fact that - // TextEditorDecorationType are very expensive to create (which makes - // incremental updates infeasible). For this reason one - // TextEditorDecorationType is used per scope. - const ranges = this.getDecorationRanges(fileUri); - vscode.window.visibleTextEditors.forEach((e) => { - if (e.document.uri.toString() !== fileUriStr) - return; - this.decorationTypes.forEach((d, i) => e.setDecorations(d, ranges[i])); - }); - } - - // Called when a text document is closed. Removes any highlighting entries for - // the text document that was closed. - public removeFileHighlightings(fileUri: vscode.Uri) { - // If there exists no entry the call to delete just returns false. - this.files.delete(fileUri.toString()); - } - - // Gets the uris as strings for the currently visible text editors. - protected getVisibleTextEditorUris(): vscode.Uri[] { - return vscode.window.visibleTextEditors.map((e) => e.document.uri); - } - - // Returns the ranges that should be used when decorating. Index i in the - // range array has the decoration type at index i of this.decorationTypes. - protected getDecorationRanges(fileUri: vscode.Uri): vscode.Range[][] { - const fileUriStr = fileUri.toString(); - if (!this.files.has(fileUriStr)) - // this.files should always have an entry for fileUri if we are here. But - // if there isn't one we don't want to crash the extension. This is also - // useful for tests. - return []; - const lines: SemanticHighlightingLine[] = - Array.from(this.files.get(fileUriStr).values()); - const decorations: vscode.Range[][] = this.decorationTypes.map(() => []); - lines.forEach((line) => { - line.tokens.forEach((token) => { - decorations[token.scopeIndex].push(new vscode.Range( - new vscode.Position(line.line, token.character), - new vscode.Position(line.line, token.character + token.length))); - }); - }); - return decorations; - } -} - -// A rule for how to color TextMate scopes. -interface TokenColorRule { - // A TextMate scope that specifies the context of the token, e.g. - // "entity.name.function.cpp". - scope: string; - // foreground is the color tokens of this scope should have. - foreground: string; -} - -export class ThemeRuleMatcher { - // The rules for the theme. - private themeRules: TokenColorRule[]; - // A cache for the getBestThemeRule function. - private bestRuleCache: Map = new Map(); - constructor(rules: TokenColorRule[]) { this.themeRules = rules; } - // Returns the best rule for a scope. - getBestThemeRule(scope: string): TokenColorRule { - if (this.bestRuleCache.has(scope)) - return this.bestRuleCache.get(scope); - let bestRule: TokenColorRule = {scope : '', foreground : ''}; - this.themeRules.forEach((rule) => { - // The best rule for a scope is the rule that is the longest prefix of the - // scope (unless a perfect match exists in which case the perfect match is - // the best). If a rule is not a prefix and we tried to match with longest - // common prefix instead variables would be highlighted as `less` - // variables when using Light+ (as variable.other would be matched against - // variable.other.less in this case). Doing common prefix matching also - // means we could match variable.cpp to variable.css if variable.css - // occurs before variable in themeRules. - // FIXME: This is not defined in the TextMate standard (it is explicitly - // undefined, https://macromates.com/manual/en/scope_selectors). Might - // want to rank some other way. - if (scope.startsWith(rule.scope) && - rule.scope.length > bestRule.scope.length) - // This rule matches and is more specific than the old rule. - bestRule = rule; - }); - this.bestRuleCache.set(scope, bestRule); - return bestRule; - } -} - -// Get all token color rules provided by the theme. -function loadTheme(themeName: string): Promise { - const extension = - vscode.extensions.all.find((extension: vscode.Extension) => { - const contribs = extension.packageJSON.contributes; - if (!contribs || !contribs.themes) - return false; - return contribs.themes.some((theme: any) => theme.id === themeName || - theme.label === themeName); - }); - - if (!extension) { - return Promise.reject('Could not find a theme with name: ' + themeName); - } - - const themeInfo = extension.packageJSON.contributes.themes.find( - (theme: any) => theme.id === themeName || theme.label === themeName); - return parseThemeFile(path.join(extension.extensionPath, themeInfo.path)); -} - -/** - * Parse the TextMate theme at fullPath. If there are multiple TextMate scopes - * of the same name in the include chain only the earliest entry of the scope is - * saved. - * @param fullPath The absolute path to the theme. - * @param seenScopes A set containing the name of the scopes that have already - * been set. - */ -export async function parseThemeFile( - fullPath: string, seenScopes?: Set): Promise { - if (!seenScopes) - seenScopes = new Set(); - // FIXME: Add support for themes written as .tmTheme. - if (path.extname(fullPath) === '.tmTheme') - return []; - try { - const contents = await readFileText(fullPath); - const parsed = jsonc.parse(contents); - const rules: TokenColorRule[] = []; - // To make sure it does not crash if tokenColors is undefined. - if (!parsed.tokenColors) - parsed.tokenColors = []; - parsed.tokenColors.forEach((rule: any) => { - if (!rule.scope || !rule.settings || !rule.settings.foreground) - return; - const textColor = rule.settings.foreground; - // Scopes that were found further up the TextMate chain should not be - // overwritten. - const addColor = (scope: string) => { - if (seenScopes.has(scope)) - return; - rules.push({scope, foreground : textColor}); - seenScopes.add(scope); - }; - if (rule.scope instanceof Array) { - return rule.scope.forEach((s: string) => addColor(s)); - } - addColor(rule.scope); - }); - - if (parsed.include) - // Get all includes and merge into a flat list of parsed json. - return [ - ...(await parseThemeFile( - path.join(path.dirname(fullPath), parsed.include), seenScopes)), - ...rules - ]; - return rules; - } catch (err) { - // If there is an error opening a file, the TextMate files that were - // correctly found and parsed further up the chain should be returned. - // Otherwise there will be no highlightings at all. - console.warn('Could not open file: ' + fullPath + ', error: ', err); - } - - return []; -} - -function readFileText(path: string): Promise { - return new Promise((resolve, reject) => { - fs.readFile(path, 'utf8', (err, data) => { - if (err) { - return reject(err); - } - return resolve(data); - }); - }); -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc b/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc deleted file mode 100644 index 6f0032c64a762e3e2c7f97bcfb1bb02096a42e30..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc +++ /dev/null @@ -1,28 +0,0 @@ -{ - // Some comment - "include": "simpleTheme.jsonc", - "name": "TestTheme", - "type": "dark", - "colors": { - "dropdown.background": "#fff" - }, - "tokenColors": [ - { - "settings": { - "foreground": "#fff" - } - }, - { - "scope": "a", - "settings": { - "foreground": "#fff" - } - }, - { - "scope": ["a", "b"], - "settings": { - "foreground": "#000" - } - } - ] -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc b/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc deleted file mode 100644 index 59a3ad61177b2c5a58f0766ec36bb8125a255ee0..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc +++ /dev/null @@ -1,17 +0,0 @@ -{ - // Some comment - "tokenColors": [ - { - "scope": "a", - "settings": { - "foreground": "#ff0000" - } - }, - { - "scope": "c", - "settings": { - "foreground": "#bcd" - } - } - ] -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts deleted file mode 100644 index 19691d69e49e1cba448c4bd13c15a7fadb99ddde..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** The module 'assert' provides assertion methods from node */ -import * as assert from 'assert'; - -import * as vscode from 'vscode'; -import * as myExtension from '../src/extension'; - -// TODO: add tests -suite("Extension Tests", () => { - // Defines a Mocha unit test - test("Something 1", () => { - assert.equal(-1, [ 1, 2, 3 ].indexOf(5)); - assert.equal(-1, [ 1, 2, 3 ].indexOf(0)); - }); -}); \ No newline at end of file diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts deleted file mode 100644 index 6e8047acbcec9b8c30a6d3cc908a23aee418e266..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as glob from 'glob'; -import * as Mocha from 'mocha'; -import * as path from 'path'; - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ui : 'tdd'}); - mocha.useColors(true); - - const testsRoot = path.resolve(__dirname, '..'); - - return new Promise((c, e) => { - glob('**/**.test.js', {cwd : testsRoot}, (err, files) => { - if (err) { - return e(err); - } - - // Add files to the test suite - files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - mocha.run(failures => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - e(err); - } - }); - }); -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/runTest.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/runTest.ts deleted file mode 100644 index 72ff0481a0c863c7387b2fcf11d1f0d5f295de13..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/runTest.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as path from 'path'; - -import {runTests} from 'vscode-test'; - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../'); - - // The path to the extension test script - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './index'); - - // Download VS Code, unzip it and run the integration test - await runTests({extensionDevelopmentPath, extensionTestsPath}); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -main(); diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts deleted file mode 100644 index 9f3e8bd9371f88ae672a8efafec4fe7e27e347e6..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; - -import * as semanticHighlighting from '../src/semantic-highlighting'; - -suite('SemanticHighlighting Tests', () => { - test('Parses arrays of textmate themes.', async () => { - const themePath = - path.join(__dirname, '../../test/assets/includeTheme.jsonc'); - const scopeColorRules = - await semanticHighlighting.parseThemeFile(themePath); - const getScopeRule = (scope: string) => - scopeColorRules.find((v) => v.scope === scope); - assert.equal(scopeColorRules.length, 3); - assert.deepEqual(getScopeRule('a'), {scope : 'a', foreground : '#fff'}); - assert.deepEqual(getScopeRule('b'), {scope : 'b', foreground : '#000'}); - assert.deepEqual(getScopeRule('c'), {scope : 'c', foreground : '#bcd'}); - }); - test('Decodes tokens correctly', () => { - const testCases: string[] = [ - 'AAAAAAABAAA=', 'AAAAAAADAAkAAAAEAAEAAA==', - 'AAAAAAADAAkAAAAEAAEAAAAAAAoAAQAA' - ]; - const expected = [ - [ {character : 0, scopeIndex : 0, length : 1} ], - [ - {character : 0, scopeIndex : 9, length : 3}, - {character : 4, scopeIndex : 0, length : 1} - ], - [ - {character : 0, scopeIndex : 9, length : 3}, - {character : 4, scopeIndex : 0, length : 1}, - {character : 10, scopeIndex : 0, length : 1} - ] - ]; - testCases.forEach( - (testCase, i) => assert.deepEqual( - semanticHighlighting.decodeTokens(testCase), expected[i])); - }); - test('ScopeRules overrides for more specific themes', () => { - const rules = [ - {scope : 'variable.other.css', foreground : '1'}, - {scope : 'variable.other', foreground : '2'}, - {scope : 'storage', foreground : '3'}, - {scope : 'storage.static', foreground : '4'}, - {scope : 'storage', foreground : '5'}, - {scope : 'variable.other.parameter', foreground : '6'}, - ]; - const tm = new semanticHighlighting.ThemeRuleMatcher(rules); - assert.deepEqual(tm.getBestThemeRule('variable.other.cpp').scope, - 'variable.other'); - assert.deepEqual(tm.getBestThemeRule('storage.static').scope, - 'storage.static'); - assert.deepEqual( - tm.getBestThemeRule('storage'), - rules[2]); // Match the first element if there are duplicates. - assert.deepEqual(tm.getBestThemeRule('variable.other.parameter').scope, - 'variable.other.parameter'); - assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope, - 'variable.other.parameter'); - }); - test('Colorizer groups decorations correctly', async () => { - const scopeTable = [ - [ 'variable' ], [ 'entity.type.function' ], - [ 'entity.type.function.method' ] - ]; - // Create the scope source ranges the highlightings should be highlighted - // at. Assumes the scopes used are the ones in the "scopeTable" variable. - const createHighlightingScopeRanges = - (highlightingLines: - semanticHighlighting.SemanticHighlightingLine[]) => { - // Initialize the scope ranges list to the correct size. Otherwise - // scopes that don't have any highlightings are missed. - let scopeRanges: vscode.Range[][] = scopeTable.map(() => []); - highlightingLines.forEach((line) => { - line.tokens.forEach((token) => { - scopeRanges[token.scopeIndex].push(new vscode.Range( - new vscode.Position(line.line, token.character), - new vscode.Position(line.line, - token.character + token.length))); - }); - }); - return scopeRanges; - }; - - const fileUri1 = vscode.Uri.parse('file:///file1'); - const fileUri2 = vscode.Uri.parse('file:///file2'); - const fileUri1Str = fileUri1.toString(); - const fileUri2Str = fileUri2.toString(); - - class MockHighlighter extends semanticHighlighting.Highlighter { - applicationUriHistory: string[] = []; - // Override to make the highlighting calls accessible to the test. Also - // makes the test not depend on visible text editors. - applyHighlights(fileUri: vscode.Uri) { - this.applicationUriHistory.push(fileUri.toString()); - } - // Override to make it accessible from the test. - getDecorationRanges(fileUri: vscode.Uri) { - return super.getDecorationRanges(fileUri); - } - // Override to make tests not depend on visible text editors. - getVisibleTextEditorUris() { return [ fileUri1, fileUri2 ]; } - } - const highlighter = new MockHighlighter(scopeTable); - const tm = new semanticHighlighting.ThemeRuleMatcher([ - {scope : 'variable', foreground : '1'}, - {scope : 'entity.type', foreground : '2'}, - ]); - // Recolorizes when initialized. - highlighter.highlight(fileUri1, []); - assert.deepEqual(highlighter.applicationUriHistory, [ fileUri1Str ]); - highlighter.initialize(tm); - assert.deepEqual(highlighter.applicationUriHistory, - [ fileUri1Str, fileUri1Str, fileUri2Str ]); - // Groups decorations into the scopes used. - let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [ - { - line : 1, - tokens : [ - {character : 1, length : 2, scopeIndex : 1}, - {character : 10, length : 2, scopeIndex : 2}, - ] - }, - { - line : 2, - tokens : [ - {character : 3, length : 2, scopeIndex : 1}, - {character : 6, length : 2, scopeIndex : 1}, - {character : 8, length : 2, scopeIndex : 2}, - ] - }, - ]; - - highlighter.highlight(fileUri1, highlightingsInLine); - assert.deepEqual(highlighter.applicationUriHistory, - [ fileUri1Str, fileUri1Str, fileUri2Str, fileUri1Str ]); - assert.deepEqual(highlighter.getDecorationRanges(fileUri1), - createHighlightingScopeRanges(highlightingsInLine)); - // Keeps state separate between files. - const highlightingsInLine1: - semanticHighlighting.SemanticHighlightingLine = { - line : 1, - tokens : [ - {character : 2, length : 1, scopeIndex : 0}, - ] - }; - highlighter.highlight(fileUri2, [ highlightingsInLine1 ]); - assert.deepEqual( - highlighter.applicationUriHistory, - [ fileUri1Str, fileUri1Str, fileUri2Str, fileUri1Str, fileUri2Str ]); - assert.deepEqual(highlighter.getDecorationRanges(fileUri2), - createHighlightingScopeRanges([ highlightingsInLine1 ])); - // Does full colorizations. - highlighter.highlight(fileUri1, [ highlightingsInLine1 ]); - assert.deepEqual(highlighter.applicationUriHistory, [ - fileUri1Str, fileUri1Str, fileUri2Str, fileUri1Str, fileUri2Str, - fileUri1Str - ]); - // After the incremental update to line 1, the old highlightings at line 1 - // will no longer exist in the array. - assert.deepEqual( - highlighter.getDecorationRanges(fileUri1), - createHighlightingScopeRanges( - [ highlightingsInLine1, ...highlightingsInLine.slice(1) ])); - // Closing a text document removes all highlightings for the file and no - // other files. - highlighter.removeFileHighlightings(fileUri1); - assert.deepEqual(highlighter.getDecorationRanges(fileUri1), []); - assert.deepEqual(highlighter.getDecorationRanges(fileUri2), - createHighlightingScopeRanges([ highlightingsInLine1 ])); - }); -}); diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json b/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json deleted file mode 100644 index 71a62c71da02528fc904693b54f1404fcac2b5b4..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6", - "es2015.core", - "es2015.collection", - "es2015.generator", - "es2015.iterable", - "es2015.promise", - "es2015.symbol", - "es2016.array.include" - ], - "sourceMap": true, - "rootDir": ".", - "alwaysStrict": true, - "noEmitOnError": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] -} diff --git a/clang-tools-extra/clangd/fuzzer/CMakeLists.txt b/clang-tools-extra/clangd/fuzzer/CMakeLists.txt index 90379822ac661303caee5cad706cda6eb4e69b35..778b61158304c518bd4c876a145d86f18a0c1c77 100644 --- a/clang-tools-extra/clangd/fuzzer/CMakeLists.txt +++ b/clang-tools-extra/clangd/fuzzer/CMakeLists.txt @@ -24,4 +24,5 @@ clang_target_link_libraries(clangd-fuzzer target_link_libraries(clangd-fuzzer PRIVATE clangDaemon + clangdSupport ) diff --git a/clang-tools-extra/clangd/fuzzer/clangd-fuzzer.cpp b/clang-tools-extra/clangd/fuzzer/clangd-fuzzer.cpp index 9776b0585e2b37e967c41a77625d5890d904e7ef..982d5fa292d3774e64f20eafee5b1262444c447f 100644 --- a/clang-tools-extra/clangd/fuzzer/clangd-fuzzer.cpp +++ b/clang-tools-extra/clangd/fuzzer/clangd-fuzzer.cpp @@ -15,8 +15,8 @@ #include "ClangdLSPServer.h" #include "ClangdServer.h" #include "CodeComplete.h" -#include "FSProvider.h" #include "refactor/Rename.h" +#include "support/FSProvider.h" #include #include diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp index 4c5719d0526c74b61051023b0b8b56a774be8733..67fed77034f129b5c00ca6d21741388decb62767 100644 --- a/clang-tools-extra/clangd/index/Background.cpp +++ b/clang-tools-extra/clangd/index/Background.cpp @@ -8,16 +8,10 @@ #include "index/Background.h" #include "Compiler.h" -#include "Context.h" -#include "FSProvider.h" #include "Headers.h" -#include "Logger.h" #include "ParsedAST.h" -#include "Path.h" #include "SourceCode.h" #include "Symbol.h" -#include "Threading.h" -#include "Trace.h" #include "URI.h" #include "index/BackgroundIndexLoader.h" #include "index/FileIndex.h" @@ -27,6 +21,12 @@ #include "index/Relation.h" #include "index/Serialization.h" #include "index/SymbolCollector.h" +#include "support/Context.h" +#include "support/FSProvider.h" +#include "support/Logger.h" +#include "support/Path.h" +#include "support/Threading.h" +#include "support/Trace.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Driver/Types.h" diff --git a/clang-tools-extra/clangd/index/Background.h b/clang-tools-extra/clangd/index/Background.h index 2ae11c72d5d43f4de296887e2af087c0e7a3096a..ffaea75c5d4178fcd5fe58a20d9d7d8179ef7b92 100644 --- a/clang-tools-extra/clangd/index/Background.h +++ b/clang-tools-extra/clangd/index/Background.h @@ -9,16 +9,16 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_H -#include "Context.h" -#include "FSProvider.h" #include "GlobalCompilationDatabase.h" -#include "Path.h" #include "SourceCode.h" -#include "Threading.h" #include "index/BackgroundRebuild.h" #include "index/FileIndex.h" #include "index/Index.h" #include "index/Serialization.h" +#include "support/Context.h" +#include "support/FSProvider.h" +#include "support/Path.h" +#include "support/Threading.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Threading.h" diff --git a/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp b/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp index 08bf07d8b280953c5946c71197e87c30f48660b6..5645569c9ae10e108a39d30eb8c1d85fa5d15be6 100644 --- a/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp +++ b/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp @@ -8,9 +8,9 @@ #include "index/BackgroundIndexLoader.h" #include "GlobalCompilationDatabase.h" -#include "Logger.h" -#include "Path.h" #include "index/Background.h" +#include "support/Logger.h" +#include "support/Path.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" diff --git a/clang-tools-extra/clangd/index/BackgroundIndexLoader.h b/clang-tools-extra/clangd/index/BackgroundIndexLoader.h index 0caf1b46352505cf34c13abfc1c7b450ee00549c..aa7ee39ef0bb52090f2327e9d1373b7f5001b515 100644 --- a/clang-tools-extra/clangd/index/BackgroundIndexLoader.h +++ b/clang-tools-extra/clangd/index/BackgroundIndexLoader.h @@ -9,8 +9,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_LOADER_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_LOADER_H -#include "Path.h" #include "index/Background.h" +#include "support/Path.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" diff --git a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp index b07728ee6a2c226d2e870327056cdf128131efb2..eee050b0db9ad7be5f0cc628482dbba94953b552 100644 --- a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp +++ b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp @@ -7,9 +7,9 @@ //===----------------------------------------------------------------------===// #include "GlobalCompilationDatabase.h" -#include "Logger.h" -#include "Path.h" #include "index/Background.h" +#include "support/Logger.h" +#include "support/Path.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" @@ -36,18 +36,13 @@ std::string getShardPathFromFilePath(llvm::StringRef ShardRoot, return std::string(ShardRootSS.str()); } -// Uses disk as a storage for index shards. Creates a directory called -// ".clangd/index/" under the path provided during construction. +// Uses disk as a storage for index shards. class DiskBackedIndexStorage : public BackgroundIndexStorage { std::string DiskShardRoot; public: - // Sets DiskShardRoot to (Directory + ".clangd/index/") which is the base - // directory for all shard files. - DiskBackedIndexStorage(llvm::StringRef Directory) { - llvm::SmallString<128> CDBDirectory(Directory); - llvm::sys::path::append(CDBDirectory, ".clangd", "index"); - DiskShardRoot = std::string(CDBDirectory.str()); + // Creates `DiskShardRoot` and any parents during construction. + DiskBackedIndexStorage(llvm::StringRef Directory) : DiskShardRoot(Directory) { std::error_code OK; std::error_code EC = llvm::sys::fs::create_directories(DiskShardRoot); if (EC != OK) { @@ -100,26 +95,31 @@ public: }; // Creates and owns IndexStorages for multiple CDBs. +// When a CDB root is found, shards are stored in $ROOT/.clangd/index. +// When no root is found, the fallback path is ~/.cache/clangd/index. class DiskBackedIndexStorageManager { public: DiskBackedIndexStorageManager( std::function(PathRef)> GetProjectInfo) : IndexStorageMapMu(std::make_unique()), GetProjectInfo(std::move(GetProjectInfo)) { - llvm::SmallString<128> HomeDir; - llvm::sys::path::home_directory(HomeDir); - this->HomeDir = HomeDir.str().str(); + llvm::SmallString<128> FallbackDir; + if (llvm::sys::path::cache_directory(FallbackDir)) + llvm::sys::path::append(FallbackDir, "clangd", "index"); + this->FallbackDir = FallbackDir.str().str(); } // Creates or fetches to storage from cache for the specified project. BackgroundIndexStorage *operator()(PathRef File) { std::lock_guard Lock(*IndexStorageMapMu); - Path CDBDirectory = HomeDir; - if (auto PI = GetProjectInfo(File)) - CDBDirectory = PI->SourceRoot; - auto &IndexStorage = IndexStorageMap[CDBDirectory]; + llvm::SmallString<128> StorageDir(FallbackDir); + if (auto PI = GetProjectInfo(File)) { + StorageDir = PI->SourceRoot; + llvm::sys::path::append(StorageDir, ".clangd", "index"); + } + auto &IndexStorage = IndexStorageMap[StorageDir]; if (!IndexStorage) - IndexStorage = create(CDBDirectory); + IndexStorage = create(StorageDir); return IndexStorage.get(); } @@ -132,7 +132,7 @@ private: return std::make_unique(CDBDirectory); } - Path HomeDir; + Path FallbackDir; llvm::StringMap> IndexStorageMap; std::unique_ptr IndexStorageMapMu; diff --git a/clang-tools-extra/clangd/index/BackgroundQueue.cpp b/clang-tools-extra/clangd/index/BackgroundQueue.cpp index 00d483f38005026440d3cad9dd2b26d937183671..3262a2f46d38fd2d080e0cfd749dd42b19dd0c8e 100644 --- a/clang-tools-extra/clangd/index/BackgroundQueue.cpp +++ b/clang-tools-extra/clangd/index/BackgroundQueue.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "Logger.h" #include "index/Background.h" +#include "support/Logger.h" namespace clang { namespace clangd { diff --git a/clang-tools-extra/clangd/index/BackgroundRebuild.cpp b/clang-tools-extra/clangd/index/BackgroundRebuild.cpp index 5cc61a6decb6c6abfad6a990996e65611f70014b..2aa5fa9ca812ff4ff29aa582c614d7edfdb9f4b5 100644 --- a/clang-tools-extra/clangd/index/BackgroundRebuild.cpp +++ b/clang-tools-extra/clangd/index/BackgroundRebuild.cpp @@ -9,13 +9,9 @@ #include "index/BackgroundRebuild.h" #include "Compiler.h" #include "Headers.h" -#include "Logger.h" #include "ParsedAST.h" -#include "Path.h" #include "SourceCode.h" #include "Symbol.h" -#include "Threading.h" -#include "Trace.h" #include "URI.h" #include "index/FileIndex.h" #include "index/IndexAction.h" @@ -24,6 +20,10 @@ #include "index/Relation.h" #include "index/Serialization.h" #include "index/SymbolCollector.h" +#include "support/Logger.h" +#include "support/Path.h" +#include "support/Threading.h" +#include "support/Trace.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/Hashing.h" diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp index 590bf46ec01c7ed60caecb720a5408901f2a46f2..6a94b9c1a6961f0f83ed91e96039f227758e8749 100644 --- a/clang-tools-extra/clangd/index/FileIndex.cpp +++ b/clang-tools-extra/clangd/index/FileIndex.cpp @@ -8,9 +8,7 @@ #include "FileIndex.h" #include "CollectMacros.h" -#include "Logger.h" #include "ParsedAST.h" -#include "Path.h" #include "SymbolCollector.h" #include "index/CanonicalIncludes.h" #include "index/Index.h" @@ -23,6 +21,8 @@ #include "index/SymbolID.h" #include "index/SymbolOrigin.h" #include "index/dex/Dex.h" +#include "support/Logger.h" +#include "support/Path.h" #include "clang/AST/ASTContext.h" #include "clang/Index/IndexingAction.h" #include "clang/Index/IndexingOptions.h" diff --git a/clang-tools-extra/clangd/index/FileIndex.h b/clang-tools-extra/clangd/index/FileIndex.h index 539f232a7523b257ef25b74d6675ed556315a291..5c8776659e8f346c76bf9d4d79c6d26d599532db 100644 --- a/clang-tools-extra/clangd/index/FileIndex.h +++ b/clang-tools-extra/clangd/index/FileIndex.h @@ -19,12 +19,12 @@ #include "Index.h" #include "MemIndex.h" #include "Merge.h" -#include "Path.h" #include "index/CanonicalIncludes.h" #include "index/Ref.h" #include "index/Relation.h" #include "index/Serialization.h" #include "index/Symbol.h" +#include "support/Path.h" #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/DenseSet.h" diff --git a/clang-tools-extra/clangd/index/Index.cpp b/clang-tools-extra/clangd/index/Index.cpp index 9ec4908bbbfc45f8422221096ebf031b9283fbd5..e4eb1b586cc5ea96a60ae035ff2a1f1afb33b927 100644 --- a/clang-tools-extra/clangd/index/Index.cpp +++ b/clang-tools-extra/clangd/index/Index.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "Index.h" -#include "Logger.h" +#include "support/Logger.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" diff --git a/clang-tools-extra/clangd/index/IndexAction.cpp b/clang-tools-extra/clangd/index/IndexAction.cpp index 8fd2159932b46c2b816fa9e1c5b33fcbe674bc08..9f294d4ab925291384ff2435d9649bbe96e58412 100644 --- a/clang-tools-extra/clangd/index/IndexAction.cpp +++ b/clang-tools-extra/clangd/index/IndexAction.cpp @@ -8,9 +8,9 @@ #include "IndexAction.h" #include "Headers.h" -#include "Logger.h" #include "index/Relation.h" #include "index/SymbolOrigin.h" +#include "support/Logger.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceLocation.h" diff --git a/clang-tools-extra/clangd/index/MemIndex.cpp b/clang-tools-extra/clangd/index/MemIndex.cpp index 453b226e7907417535e01fa764ea55c569f2ee66..46e9c0a8ee45ebc94fb2839e21d99f82ad0d4ead 100644 --- a/clang-tools-extra/clangd/index/MemIndex.cpp +++ b/clang-tools-extra/clangd/index/MemIndex.cpp @@ -8,9 +8,9 @@ #include "MemIndex.h" #include "FuzzyMatch.h" -#include "Logger.h" #include "Quality.h" -#include "Trace.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "clang/Index/IndexSymbol.h" namespace clang { diff --git a/clang-tools-extra/clangd/index/Merge.cpp b/clang-tools-extra/clangd/index/Merge.cpp index 0cef7dc7630a9155c8eca773ce05a1d4a7aeb9b4..a93aa204e18fb43c2fa9c3409497a34f1b09bd2e 100644 --- a/clang-tools-extra/clangd/index/Merge.cpp +++ b/clang-tools-extra/clangd/index/Merge.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "Merge.h" -#include "Logger.h" -#include "Trace.h" #include "index/Symbol.h" #include "index/SymbolLocation.h" #include "index/SymbolOrigin.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" diff --git a/clang-tools-extra/clangd/index/Serialization.cpp b/clang-tools-extra/clangd/index/Serialization.cpp index 6ba4e046189c9e58c710a97fa9cd5179ee3d068a..06527a615c202b08305de282fa94ef70b1eb3a0e 100644 --- a/clang-tools-extra/clangd/index/Serialization.cpp +++ b/clang-tools-extra/clangd/index/Serialization.cpp @@ -8,12 +8,12 @@ #include "Serialization.h" #include "Headers.h" -#include "Logger.h" #include "RIFF.h" #include "SymbolLocation.h" #include "SymbolOrigin.h" -#include "Trace.h" #include "dex/Dex.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compression.h" diff --git a/clang-tools-extra/clangd/index/Serialization.h b/clang-tools-extra/clangd/index/Serialization.h index 47317c0401fce840e723247e346e5dddae5a402d..99510630f1cacc7b27ee3e4d33075a0b8e36f94d 100644 --- a/clang-tools-extra/clangd/index/Serialization.h +++ b/clang-tools-extra/clangd/index/Serialization.h @@ -77,6 +77,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const IndexFileOut &O); std::string toYAML(const Symbol &); std::string toYAML(const std::pair> &); std::string toYAML(const Relation &); +std::string toYAML(const Ref &); + +// Deserialize a single symbol from YAML. +llvm::Expected symbolFromYAML(StringRef YAML, + llvm::UniqueStringSaver *Strings); +llvm::Expected refFromYAML(StringRef YAML, + llvm::UniqueStringSaver *Strings); // Build an in-memory static index from an index file. // The size should be relatively small, so data can be managed in memory. diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 471061672107d689d526a66f2e73b7711c384943..b502dfb03aec337914593b1c6986ac582643862a 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -12,11 +12,11 @@ #include "CodeComplete.h" #include "CodeCompletionStrings.h" #include "ExpectedTypes.h" -#include "Logger.h" #include "SourceCode.h" #include "SymbolLocation.h" #include "URI.h" #include "index/SymbolID.h" +#include "support/Logger.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -743,7 +743,11 @@ bool SymbolCollector::isSelfContainedHeader(FileID FID) { const FileEntry *FE = SM.getFileEntryForID(FID); if (!FE) return false; - if (!PP->getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE)) + // FIXME: Should files that have been #import'd be considered + // self-contained? That's really a property of the includer, + // not of the file. + if (!PP->getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE) && + !PP->getHeaderSearchInfo().hasFileBeenImported(FE)) return false; // This pattern indicates that a header can't be used without // particular preprocessor state, usually set up by another header. diff --git a/clang-tools-extra/clangd/index/YAMLSerialization.cpp b/clang-tools-extra/clangd/index/YAMLSerialization.cpp index 79965ceb1634229838c5f371a3db60702fe7215e..4f6bd927cc196c1449195a23d932b80e09d6d12d 100644 --- a/clang-tools-extra/clangd/index/YAMLSerialization.cpp +++ b/clang-tools-extra/clangd/index/YAMLSerialization.cpp @@ -17,8 +17,8 @@ #include "Serialization.h" #include "SymbolLocation.h" #include "SymbolOrigin.h" -#include "Trace.h" #include "dex/Dex.h" +#include "support/Trace.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -517,5 +517,40 @@ std::string toYAML(const Relation &R) { return Buf; } +std::string toYAML(const Ref &R) { + std::string Buf; + { + llvm::raw_string_ostream OS(Buf); + llvm::yaml::Output Yout(OS); + Ref Reference = R; // copy: Yout<< requires mutability. + Yout << Reference; + } + return Buf; +} + +llvm::Expected +symbolFromYAML(StringRef YAML, llvm::UniqueStringSaver *Strings) { + clangd::Symbol Deserialized; + llvm::yaml::Input YAMLInput(YAML, Strings); + if (YAMLInput.error()) + return llvm::make_error( + llvm::formatv("Unable to deserialize Symbol from YAML: {0}", YAML), + llvm::inconvertibleErrorCode()); + YAMLInput >> Deserialized; + return Deserialized; +} + +llvm::Expected refFromYAML(StringRef YAML, + llvm::UniqueStringSaver *Strings) { + clangd::Ref Deserialized; + llvm::yaml::Input YAMLInput(YAML, Strings); + if (YAMLInput.error()) + return llvm::make_error( + llvm::formatv("Unable to deserialize Symbol from YAML: {0}", YAML), + llvm::inconvertibleErrorCode()); + YAMLInput >> Deserialized; + return Deserialized; +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/index/dex/Dex.cpp b/clang-tools-extra/clangd/index/dex/Dex.cpp index 36ddedd04e1fcbf776c4dbaf7ed79d8a01696ead..a663e5387ece2acb1a9073333aa8f8d9713733e7 100644 --- a/clang-tools-extra/clangd/index/dex/Dex.cpp +++ b/clang-tools-extra/clangd/index/dex/Dex.cpp @@ -9,11 +9,11 @@ #include "Dex.h" #include "FileDistance.h" #include "FuzzyMatch.h" -#include "Logger.h" #include "Quality.h" -#include "Trace.h" #include "index/Index.h" #include "index/dex/Iterator.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/ScopedPrinter.h" #include diff --git a/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt b/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt index a4edbb372a7613ea78ef30f0765007aed887ed51..7b4b6e53a4ad0fabfd7a2c47a898eadf8d7f8c31 100644 --- a/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt @@ -1,4 +1,5 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) set(LLVM_LINK_COMPONENTS LineEditor @@ -16,4 +17,5 @@ clang_target_link_libraries(dexp target_link_libraries(dexp PRIVATE clangDaemon + clangdRemoteIndex ) diff --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp index 015246d1a82fb64c99fbc7ffe2638368848da373..8738f9cd144c60fa17888b69ac90e452662d15b4 100644 --- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp +++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp @@ -11,9 +11,11 @@ // //===----------------------------------------------------------------------===// +#include "Features.inc" #include "SourceCode.h" #include "index/Serialization.h" #include "index/dex/Dex.h" +#include "index/remote/Client.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -26,8 +28,9 @@ namespace clang { namespace clangd { namespace { -llvm::cl::opt IndexPath(llvm::cl::desc(""), - llvm::cl::Positional, llvm::cl::Required); +llvm::cl::opt IndexLocation( + llvm::cl::desc(""), + llvm::cl::Positional); llvm::cl::opt ExecCommand("c", llvm::cl::desc("Command to execute and then exit")); @@ -38,6 +41,10 @@ queries over given symbol collection obtained via clangd-indexer. The tool can be used to evaluate search quality of existing index implementations and manually construct non-trivial test cases. +You can connect to remote index by passing remote:address to dexp. Example: + +$ dexp remote:0.0.0.0:9000 + Type use "help" request to get information about the details. )"; @@ -150,7 +157,7 @@ class FuzzyFind : public Command { } Request.AnyScope = Request.Scopes.empty(); // FIXME(kbobyrev): Print symbol final scores to see the distribution. - static const auto OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n"; + static const auto *OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n"; llvm::outs() << llvm::formatv(OutputFormat, "Rank", "Symbol ID", "Symbol Name"); size_t Rank = 0; @@ -279,9 +286,9 @@ public: void run() { using namespace clang::clangd; // Read input file (as specified in global option) - auto Buffer = llvm::MemoryBuffer::getFile(IndexPath); + auto Buffer = llvm::MemoryBuffer::getFile(IndexLocation); if (!Buffer) { - llvm::errs() << llvm::formatv("Can't open {0}", IndexPath) << "\n"; + llvm::errs() << llvm::formatv("Can't open {0}", IndexLocation) << "\n"; return; } @@ -316,13 +323,14 @@ struct { {"find", "Search for symbols with fuzzyFind", std::make_unique}, {"lookup", "Dump symbol details by ID or qualified name", std::make_unique}, - {"refs", "Find references by ID or qualified name", - std::make_unique}, + {"refs", "Find references by ID or qualified name", std::make_unique}, {"export", "Export index", std::make_unique}, }; std::unique_ptr openIndex(llvm::StringRef Index) { - return loadIndex(Index, /*UseDex=*/true); + return Index.startswith("remote:") + ? remote::getClient(Index.drop_front(strlen("remote:"))) + : loadIndex(Index, /*UseDex=*/true); } bool runCommand(std::string Request, const SymbolIndex &Index) { @@ -365,9 +373,10 @@ int main(int argc, const char *argv[]) { llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); std::unique_ptr Index; - reportTime("Dex build", [&]() { - Index = openIndex(IndexPath); - }); + reportTime(llvm::StringRef(IndexLocation).startswith("remote:") + ? "Remote index client creation" + : "Dex build", + [&]() { Index = openIndex(IndexLocation); }); if (!Index) { llvm::outs() << "Failed to open the index.\n"; diff --git a/clang-tools-extra/clangd/index/remote/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/CMakeLists.txt index b946958f3c5f786060f9b8f81cacefd482f757ad..81287b58afa5272d4b19064ccecdb3e2e85a7f5a 100644 --- a/clang-tools-extra/clangd/index/remote/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/remote/CMakeLists.txt @@ -1,7 +1,32 @@ -generate_grpc_protos(RemoteIndexProtos "Index.proto") +if (CLANGD_ENABLE_REMOTE) + generate_grpc_protos(RemoteIndexProtos "Index.proto") + include_directories(${CMAKE_CURRENT_BINARY_DIR}) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../) -include_directories("${CMAKE_CURRENT_BINARY_DIR}") -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../) + # FIXME(kirillbobyrev): target_compile_definitions is not working with + # add_clang_library for some reason. Is there any way to make this + # target-local? + add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=1) -add_subdirectory(client) -add_subdirectory(server) + add_clang_library(clangdRemoteIndex + Client.cpp + + LINK_LIBS + RemoteIndexProtos + clangdRemoteMarshalling + + protobuf + grpc++ + clangDaemon + clangdSupport + + DEPENDS + RemoteIndexProtos + ) + + add_subdirectory(marshalling) + add_subdirectory(server) +else() + # Provides a dummy implementation of clangdRemoteIndex. + add_subdirectory(unimplemented) +endif() diff --git a/clang-tools-extra/clangd/index/remote/Client.cpp b/clang-tools-extra/clangd/index/remote/Client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ba1dfeb431d5e15c344fddcff76a3ab0d9de192 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/Client.cpp @@ -0,0 +1,102 @@ +//===--- Client.cpp ----------------------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +#include "Client.h" +#include "Index.grpc.pb.h" +#include "index/Serialization.h" +#include "marshalling/Marshalling.h" +#include "support/Logger.h" +#include "support/Trace.h" +#include "llvm/Support/YAMLTraits.h" + +namespace clang { +namespace clangd { +namespace remote { +namespace { + +class IndexClient : public clangd::SymbolIndex { + template + using StreamingCall = std::unique_ptr> ( + remote::SymbolIndex::Stub::*)(grpc::ClientContext *, const RequestT &); + + // FIXME(kirillbobyrev): Set deadlines for requests. + template + bool streamRPC(ClangdRequestT Request, + StreamingCall RPCCall, + CallbackT Callback) const { + bool FinalResult = false; + trace::Span Tracer(RequestT::descriptor()->name()); + const auto RPCRequest = toProtobuf(Request); + grpc::ClientContext Context; + auto Reader = (Stub.get()->*RPCCall)(&Context, RPCRequest); + llvm::BumpPtrAllocator Arena; + llvm::UniqueStringSaver Strings(Arena); + ReplyT Reply; + while (Reader->Read(&Reply)) { + if (!Reply.has_stream_result()) { + FinalResult = Reply.final_result(); + continue; + } + auto Sym = fromProtobuf(Reply.stream_result(), &Strings); + if (!Sym) + elog("Received invalid {0}: {1}", ReplyT::descriptor()->name(), + Reply.stream_result().yaml_serialization()); + Callback(*Sym); + } + SPAN_ATTACH(Tracer, "status", Reader->Finish().ok()); + return FinalResult; + } + +public: + IndexClient(std::shared_ptr Channel) + : Stub(remote::SymbolIndex::NewStub(Channel)) {} + + void lookup(const clangd::LookupRequest &Request, + llvm::function_ref Callback) const { + streamRPC(Request, &remote::SymbolIndex::Stub::Lookup, Callback); + } + + bool + fuzzyFind(const clangd::FuzzyFindRequest &Request, + llvm::function_ref Callback) const { + return streamRPC(Request, &remote::SymbolIndex::Stub::FuzzyFind, Callback); + } + + bool refs(const clangd::RefsRequest &Request, + llvm::function_ref Callback) const { + return streamRPC(Request, &remote::SymbolIndex::Stub::Refs, Callback); + } + + // FIXME(kirillbobyrev): Implement this. + void + relations(const clangd::RelationsRequest &, + llvm::function_ref) + const {} + + // IndexClient does not take any space since the data is stored on the server. + size_t estimateMemoryUsage() const { return 0; } + +private: + std::unique_ptr Stub; +}; + +} // namespace + +std::unique_ptr getClient(llvm::StringRef Address) { + const auto Channel = + grpc::CreateChannel(Address.str(), grpc::InsecureChannelCredentials()); + Channel->GetState(true); + return std::unique_ptr(new IndexClient(Channel)); +} + +} // namespace remote +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/index/remote/Client.h b/clang-tools-extra/clangd/index/remote/Client.h new file mode 100644 index 0000000000000000000000000000000000000000..9708fdbe851aefb6c22f149c9247da611297bc20 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/Client.h @@ -0,0 +1,31 @@ +//===--- Client.h - Connect to a remote index via gRPC -----------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H + +#include "index/Index.h" + +namespace clang { +namespace clangd { +namespace remote { + +/// Returns an SymbolIndex client that passes requests to remote index located +/// at \p Address. The client allows synchronous RPC calls. +/// +/// This method attempts to resolve the address and establish the connection. +/// +/// \returns nullptr if the address is not resolved during the function call or +/// if the project was compiled without Remote Index support. +std::unique_ptr getClient(llvm::StringRef Address); + +} // namespace remote +} // namespace clangd +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H diff --git a/clang-tools-extra/clangd/index/remote/Index.proto b/clang-tools-extra/clangd/index/remote/Index.proto index 399036ed72b7125018162f484e80fa7320c8ce9d..0cd9738db58cb0a218343e93f032561b5aa44b04 100644 --- a/clang-tools-extra/clangd/index/remote/Index.proto +++ b/clang-tools-extra/clangd/index/remote/Index.proto @@ -10,10 +10,60 @@ syntax = "proto3"; package clang.clangd.remote; -service Index { +service SymbolIndex { rpc Lookup(LookupRequest) returns (stream LookupReply) {} + + rpc FuzzyFind(FuzzyFindRequest) returns (stream FuzzyFindReply) {} + + rpc Refs(RefsRequest) returns (stream RefsReply) {} +} + +message LookupRequest { repeated string ids = 1; } + +// The response is a stream of symbol messages and the terminating message +// indicating the end of stream. +message LookupReply { + oneof kind { + Symbol stream_result = 1; + bool final_result = 2; + } +} + +message FuzzyFindRequest { + string query = 1; + repeated string scopes = 2; + bool any_scope = 3; + uint32 limit = 4; + bool resricted_for_code_completion = 5; + repeated string proximity_paths = 6; + repeated string preferred_types = 7; +} + +// The response is a stream of symbol messages, and one terminating has_more +// message. +message FuzzyFindReply { + oneof kind { + Symbol stream_result = 1; + bool final_result = 2; // HasMore + } } -message LookupRequest { string id = 1; } +message RefsRequest { + repeated string ids = 1; + uint32 filter = 2; + uint32 limit = 3; +} + +// The response is a stream of reference messages, and one terminating has_more +// message. +message RefsReply { + oneof kind { + Ref stream_result = 1; + bool final_result = 2; // HasMore + } +} -message LookupReply { string symbol_yaml = 1; } +// FIXME(kirillbobyrev): Properly serialize symbols and refs instead of passing +// YAML. +message Ref { string yaml_serialization = 1; } +message Symbol { string yaml_serialization = 1; } diff --git a/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt deleted file mode 100644 index 18bca1b04436d0a1c5731d4b37a4fd2365016035..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(LLVM_LINK_COMPONENTS - LineEditor - Support - ) -add_clang_executable(clangd-index-client - Client.cpp - ) -target_compile_definitions(clangd-index-client PRIVATE -DGOOGLE_PROTOBUF_NO_RTTI=1) -clang_target_link_libraries(clangd-index-client - PRIVATE - clangDaemon - ) -target_link_libraries(clangd-index-client - PRIVATE - RemoteIndexProtos - - protobuf - grpc++ - ) diff --git a/clang-tools-extra/clangd/index/remote/client/Client.cpp b/clang-tools-extra/clangd/index/remote/client/Client.cpp deleted file mode 100644 index 5e888c5e0fa7f4233be19faecf3c32de9f703082..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/index/remote/client/Client.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//===--- Client.cpp - Remote Index Client -----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements a simple interactive tool which can be used to manually -// evaluate symbol search quality of Clangd index. -// -//===----------------------------------------------------------------------===// - -#include "SourceCode.h" -#include "index/Serialization.h" -#include "index/dex/Dex.h" -#include "llvm/ADT/ScopeExit.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/LineEditor/LineEditor.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Signals.h" - -#include "grpcpp/grpcpp.h" - -#include "Index.grpc.pb.h" - -namespace clang { -namespace clangd { -namespace { - -llvm::cl::opt - ServerAddress("server-address", - llvm::cl::desc("Address of remote index server to use."), - llvm::cl::init("0.0.0.0:50051")); - -static const std::string Overview = R"( -This is an **experimental** interactive tool to process user-provided search -queries over given symbol collection obtained via clangd-indexer with the help -of remote index server. The client will connect to remote index server and pass -it lookup queries. -)"; - -class RemoteIndexClient { -public: - RemoteIndexClient(std::shared_ptr Channel) - : Stub(remote::Index::NewStub(Channel)) {} - - void lookup(llvm::StringRef ID) { - llvm::outs() << "Lookup of symbol with ID " << ID << '\n'; - remote::LookupRequest Proto; - Proto.set_id(ID.str()); - - grpc::ClientContext Context; - remote::LookupReply Reply; - std::unique_ptr> Reader( - Stub->Lookup(&Context, Proto)); - while (Reader->Read(&Reply)) { - llvm::outs() << Reply.symbol_yaml(); - } - grpc::Status Status = Reader->Finish(); - if (Status.ok()) { - llvm::outs() << "lookupRequest rpc succeeded.\n"; - } else { - llvm::outs() << "lookupRequest rpc failed.\n"; - } - } - -private: - std::unique_ptr Stub; -}; - -} // namespace -} // namespace clangd -} // namespace clang - -int main(int argc, const char *argv[]) { - using namespace clang::clangd; - - llvm::cl::ParseCommandLineOptions(argc, argv, Overview); - llvm::cl::ResetCommandLineParser(); // We reuse it for REPL commands. - llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); - - RemoteIndexClient IndexClient( - grpc::CreateChannel(ServerAddress, grpc::InsecureChannelCredentials())); - - llvm::LineEditor LE("remote-index-client"); - while (llvm::Optional Request = LE.readLine()) - IndexClient.lookup(std::move(*Request)); -} diff --git a/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..75e57edd45d9444ab2fd5ae17b0513db8e9c41b8 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt @@ -0,0 +1,13 @@ +add_clang_library(clangdRemoteMarshalling + Marshalling.cpp + + LINK_LIBS + RemoteIndexProtos + + protobuf + clangDaemon + clangdSupport + + DEPENDS + RemoteIndexProtos + ) diff --git a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60a258a6db2e98edec62c6215d630b55d6d9743e --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp @@ -0,0 +1,99 @@ +//===--- Marshalling.cpp -----------------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Marshalling.h" +#include "index/Serialization.h" +#include "support/Logger.h" + +namespace clang { +namespace clangd { +namespace remote { + +clangd::FuzzyFindRequest fromProtobuf(const FuzzyFindRequest *Request) { + clangd::FuzzyFindRequest Result; + Result.Query = Request->query(); + for (const auto &Scope : Request->scopes()) + Result.Scopes.push_back(Scope); + Result.AnyScope = Request->any_scope(); + if (Request->limit()) + Result.Limit = Request->limit(); + Result.RestrictForCodeCompletion = Request->resricted_for_code_completion(); + for (const auto &Path : Request->proximity_paths()) + Result.ProximityPaths.push_back(Path); + for (const auto &Type : Request->preferred_types()) + Result.ProximityPaths.push_back(Type); + return Result; +} + +llvm::Optional fromProtobuf(const Symbol &Message, + llvm::UniqueStringSaver *Strings) { + auto Result = symbolFromYAML(Message.yaml_serialization(), Strings); + if (!Result) { + elog("Cannot convert Symbol from Protobuf: {}", Result.takeError()); + return llvm::None; + } + return *Result; +} +llvm::Optional fromProtobuf(const Ref &Message, + llvm::UniqueStringSaver *Strings) { + auto Result = refFromYAML(Message.yaml_serialization(), Strings); + if (!Result) { + elog("Cannot convert Ref from Protobuf: {}", Result.takeError()); + return llvm::None; + } + return *Result; +} + +LookupRequest toProtobuf(const clangd::LookupRequest &From) { + LookupRequest RPCRequest; + for (const auto &SymbolID : From.IDs) + RPCRequest.add_ids(SymbolID.str()); + return RPCRequest; +} + +FuzzyFindRequest toProtobuf(const clangd::FuzzyFindRequest &From) { + FuzzyFindRequest RPCRequest; + RPCRequest.set_query(From.Query); + for (const auto &Scope : From.Scopes) + RPCRequest.add_scopes(Scope); + RPCRequest.set_any_scope(From.AnyScope); + if (From.Limit) + RPCRequest.set_limit(*From.Limit); + RPCRequest.set_resricted_for_code_completion(From.RestrictForCodeCompletion); + for (const auto &Path : From.ProximityPaths) + RPCRequest.add_proximity_paths(Path); + for (const auto &Type : From.PreferredTypes) + RPCRequest.add_preferred_types(Type); + return RPCRequest; +} + +RefsRequest toProtobuf(const clangd::RefsRequest &From) { + RefsRequest RPCRequest; + for (const auto &ID : From.IDs) + RPCRequest.add_ids(ID.str()); + RPCRequest.set_filter(static_cast(From.Filter)); + if (From.Limit) + RPCRequest.set_limit(*From.Limit); + return RPCRequest; +} + +Symbol toProtobuf(const clangd::Symbol &From) { + Symbol Result; + Result.set_yaml_serialization(toYAML(From)); + return Result; +} + +Ref toProtobuf(const clangd::Ref &From) { + Ref Result; + Result.set_yaml_serialization(toYAML(From)); + return Result; +} + +} // namespace remote +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h new file mode 100644 index 0000000000000000000000000000000000000000..ae58318e3dbb17017db63f4533aaf09945dd74c1 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h @@ -0,0 +1,41 @@ +//===--- Marshalling.h -------------------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Transformations between native Clangd types and Protobuf-generated classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H + +#include "Index.grpc.pb.h" +#include "index/Index.h" +#include "llvm/Support/StringSaver.h" + +namespace clang { +namespace clangd { +namespace remote { + +clangd::FuzzyFindRequest fromProtobuf(const FuzzyFindRequest *Request); +llvm::Optional fromProtobuf(const Symbol &Message, + llvm::UniqueStringSaver *Strings); +llvm::Optional fromProtobuf(const Ref &Message, + llvm::UniqueStringSaver *Strings); + +LookupRequest toProtobuf(const clangd::LookupRequest &From); +FuzzyFindRequest toProtobuf(const clangd::FuzzyFindRequest &From); +RefsRequest toProtobuf(const clangd::RefsRequest &From); + +Ref toProtobuf(const clangd::Ref &From); +Symbol toProtobuf(const clangd::Symbol &From); + +} // namespace remote +} // namespace clangd +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H diff --git a/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt index 7493be1a444ff24cccf365bb673bb191816bff0c..b87541f98ef4b020011371db20978aba974b713f 100644 --- a/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt @@ -4,17 +4,16 @@ set(LLVM_LINK_COMPONENTS ) add_clang_executable(clangd-index-server Server.cpp - ) -target_compile_definitions(clangd-index-server PRIVATE -DGOOGLE_PROTOBUF_NO_RTTI=1) -clang_target_link_libraries(clangd-index-server - PRIVATE - clangDaemon + + DEPENDS + RemoteIndexProtos ) target_link_libraries(clangd-index-server PRIVATE + clangDaemon + RemoteIndexProtos + clangdRemoteMarshalling - protobuf grpc++ - clangDaemon ) diff --git a/clang-tools-extra/clangd/index/remote/server/Server.cpp b/clang-tools-extra/clangd/index/remote/server/Server.cpp index b7a54b79b6c333bd0f8454b191fc4d47099187db..ca35ff7715f04d45f9232e4429a593f01bf549dd 100644 --- a/clang-tools-extra/clangd/index/remote/server/Server.cpp +++ b/clang-tools-extra/clangd/index/remote/server/Server.cpp @@ -8,6 +8,7 @@ #include "index/Index.h" #include "index/Serialization.h" +#include "index/remote/marshalling/Marshalling.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/LineEditor/LineEditor.h" @@ -16,13 +17,14 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" -#include "grpcpp/grpcpp.h" -#include "grpcpp/health_check_service_interface.h" +#include +#include #include "Index.grpc.pb.h" namespace clang { namespace clangd { +namespace remote { namespace { static const std::string Overview = R"( @@ -33,42 +35,80 @@ awaits gRPC lookup requests from the client. llvm::cl::opt IndexPath(llvm::cl::desc(""), llvm::cl::Positional, llvm::cl::Required); -llvm::cl::opt ServerAddress("server-address", - llvm::cl::init("0.0.0.0:50051")); +llvm::cl::opt ServerAddress( + "server-address", llvm::cl::init("0.0.0.0:50051"), + llvm::cl::desc("Address of the invoked server. Defaults to 0.0.0.0:50051")); -std::unique_ptr openIndex(llvm::StringRef Index) { +std::unique_ptr openIndex(llvm::StringRef Index) { return loadIndex(Index, /*UseIndex=*/true); } -class RemoteIndexServer final : public remote::Index::Service { +class RemoteIndexServer final : public SymbolIndex::Service { public: - RemoteIndexServer(std::unique_ptr Index) + RemoteIndexServer(std::unique_ptr Index) : Index(std::move(Index)) {} private: grpc::Status Lookup(grpc::ServerContext *Context, - const remote::LookupRequest *Request, - grpc::ServerWriter *Reply) override { - llvm::outs() << "Lookup of symbol with ID " << Request->id() << '\n'; - LookupRequest Req; - auto SID = SymbolID::fromStr(Request->id()); - if (!SID) { - llvm::outs() << llvm::toString(SID.takeError()) << "\n"; - return grpc::Status::CANCELLED; + const LookupRequest *Request, + grpc::ServerWriter *Reply) override { + clangd::LookupRequest Req; + for (const auto &ID : Request->ids()) { + auto SID = SymbolID::fromStr(StringRef(ID)); + if (!SID) + return grpc::Status::CANCELLED; + Req.IDs.insert(*SID); } - Req.IDs.insert(*SID); - Index->lookup(Req, [&](const Symbol &Sym) { - remote::LookupReply NextSymbol; - NextSymbol.set_symbol_yaml(toYAML(Sym)); - Reply->Write(NextSymbol); + Index->lookup(Req, [&](const clangd::Symbol &Sym) { + LookupReply NextMessage; + *NextMessage.mutable_stream_result() = toProtobuf(Sym); + Reply->Write(NextMessage); }); + LookupReply LastMessage; + LastMessage.set_final_result(true); + Reply->Write(LastMessage); return grpc::Status::OK; } - std::unique_ptr Index; + grpc::Status FuzzyFind(grpc::ServerContext *Context, + const FuzzyFindRequest *Request, + grpc::ServerWriter *Reply) override { + const auto Req = fromProtobuf(Request); + bool HasMore = Index->fuzzyFind(Req, [&](const clangd::Symbol &Sym) { + FuzzyFindReply NextMessage; + *NextMessage.mutable_stream_result() = toProtobuf(Sym); + Reply->Write(NextMessage); + }); + FuzzyFindReply LastMessage; + LastMessage.set_final_result(HasMore); + Reply->Write(LastMessage); + return grpc::Status::OK; + } + + grpc::Status Refs(grpc::ServerContext *Context, const RefsRequest *Request, + grpc::ServerWriter *Reply) override { + clangd::RefsRequest Req; + for (const auto &ID : Request->ids()) { + auto SID = SymbolID::fromStr(StringRef(ID)); + if (!SID) + return grpc::Status::CANCELLED; + Req.IDs.insert(*SID); + } + bool HasMore = Index->refs(Req, [&](const clangd::Ref &Reference) { + RefsReply NextMessage; + *NextMessage.mutable_stream_result() = toProtobuf(Reference); + Reply->Write(NextMessage); + }); + RefsReply LastMessage; + LastMessage.set_final_result(HasMore); + Reply->Write(LastMessage); + return grpc::Status::OK; + } + + std::unique_ptr Index; }; -void runServer(std::unique_ptr Index, +void runServer(std::unique_ptr Index, const std::string &ServerAddress) { RemoteIndexServer Service(std::move(Index)); @@ -83,15 +123,16 @@ void runServer(std::unique_ptr Index, } } // namespace +} // namespace remote } // namespace clangd } // namespace clang int main(int argc, char *argv[]) { - using namespace clang::clangd; - llvm::cl::ParseCommandLineOptions(argc, argv, clang::clangd::Overview); + using namespace clang::clangd::remote; + llvm::cl::ParseCommandLineOptions(argc, argv, Overview); llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); - std::unique_ptr Index = openIndex(IndexPath); + std::unique_ptr Index = openIndex(IndexPath); if (!Index) { llvm::outs() << "Failed to open the index.\n"; diff --git a/clang-tools-extra/clangd/index/remote/unimplemented/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/unimplemented/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5d223ad3c8b3542b5f4cb80ae9e3a4e62851c113 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/unimplemented/CMakeLists.txt @@ -0,0 +1,11 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../) +# When compiled without Remote Index support, the real implementation index +# client is not present. Users will get a notification about this when trying +# to connect to remote index server instance. +add_clang_library(clangdRemoteIndex + UnimplementedClient.cpp + + LINK_LIBS + clangDaemon + clangdSupport + ) diff --git a/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp b/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0fb612f6332fe58a1cf8d0bd105d6a9ae6222cf --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp @@ -0,0 +1,23 @@ +//===--- UnimplementedClient.cpp ---------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "index/remote/Client.h" +#include "support/Logger.h" + +namespace clang { +namespace clangd { +namespace remote { + +std::unique_ptr getClient(llvm::StringRef Address) { + elog("Can't create SymbolIndex client without Remote Index support."); + return nullptr; +} + +} // namespace remote +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index 0585897947dfc61393689d8bf1eec712844a29ed..c08f6ea805aaa28f26a6e04cb5c3a6114aff355e 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -9,12 +9,12 @@ #include "refactor/Rename.h" #include "AST.h" #include "FindTarget.h" -#include "Logger.h" #include "ParsedAST.h" #include "Selection.h" #include "SourceCode.h" -#include "Trace.h" #include "index/SymbolCollector.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/SourceLocation.h" diff --git a/clang-tools-extra/clangd/refactor/Rename.h b/clang-tools-extra/clangd/refactor/Rename.h index 5c53ba633fa2b1e9deb27f66e4e63a6814687a5f..e27951605ebcafb1a2cb566d5767de7e8c947df9 100644 --- a/clang-tools-extra/clangd/refactor/Rename.h +++ b/clang-tools-extra/clangd/refactor/Rename.h @@ -9,9 +9,9 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_RENAME_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_RENAME_H -#include "Path.h" #include "Protocol.h" #include "SourceCode.h" +#include "support/Path.h" #include "clang/Basic/LangOptions.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/Support/Error.h" diff --git a/clang-tools-extra/clangd/refactor/Tweak.cpp b/clang-tools-extra/clangd/refactor/Tweak.cpp index 3e3033ce5c7a5e86ab0fe8086246be5ca77cb5e1..b1f4dcd69af6bfaae8f262cf488d877ee8fb3251 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.cpp +++ b/clang-tools-extra/clangd/refactor/Tweak.cpp @@ -6,10 +6,10 @@ // //===----------------------------------------------------------------------===// #include "Tweak.h" -#include "Logger.h" -#include "Path.h" #include "SourceCode.h" #include "index/Index.h" +#include "support/Logger.h" +#include "support/Path.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" diff --git a/clang-tools-extra/clangd/refactor/Tweak.h b/clang-tools-extra/clangd/refactor/Tweak.h index 84d3bdb3fc0a0cd0c9db503b7683829a9eb85dc1..10e3e8d3e56530490f17bd81219c7d8745f85774 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.h +++ b/clang-tools-extra/clangd/refactor/Tweak.h @@ -20,11 +20,11 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_ACTIONS_TWEAK_H #include "ParsedAST.h" -#include "Path.h" #include "Protocol.h" #include "Selection.h" #include "SourceCode.h" #include "index/Index.h" +#include "support/Path.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp index f2ef235c43f791119dbed4b8df495a8a9f5b792c..836ac9ac57abf9b6897dc1bc5cd0e06016998c2e 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp @@ -8,8 +8,8 @@ #include "AST.h" #include "FindTarget.h" -#include "Logger.h" #include "refactor/Tweak.h" +#include "support/Logger.h" #include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt b/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt index 995288bca2cf479ce4565d82a60c0bba5affd352..c5bff2f34a9a2783d11686de9bcdbc4983b775dd 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt +++ b/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangDaemonTweaks OBJECT clangAST clangBasic clangDaemon + clangdSupport clangFormat clangLex clangToolingCore diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp index b1057d8b80e789b7be826420c5cc1de4a7b1c336..e28a2c46c374a68788636f6e1c687cffd0b4eccc 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp @@ -8,11 +8,11 @@ #include "AST.h" #include "FindTarget.h" -#include "Logger.h" #include "Selection.h" #include "SourceCode.h" #include "XRefs.h" #include "refactor/Tweak.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp index c2d344a3a46ef90f95464c2d91b54baa21293677..405ff90a5945cfe092d074b0177912214dc32b32 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp @@ -9,12 +9,12 @@ #include "AST.h" #include "FindTarget.h" #include "HeaderSourceSwitch.h" -#include "Logger.h" #include "ParsedAST.h" -#include "Path.h" #include "Selection.h" #include "SourceCode.h" #include "refactor/Tweak.h" +#include "support/Logger.h" +#include "support/Path.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp index bffd6c02fb6e9d3b70bb323ccf98563cd26b6d91..d2dfc4a537d4aadb31b6457a0876f8454f1a544f 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp @@ -7,20 +7,20 @@ //===----------------------------------------------------------------------===// #include "refactor/Tweak.h" -#include "Logger.h" +#include "XRefs.h" +#include "support/Logger.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" +#include #include #include #include -#include -#include "XRefs.h" -#include "llvm/ADT/StringExtras.h" namespace clang { namespace clangd { diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp index a22b5ab60cd5289c4c8aa9207196ba51966a0cd0..dd62670646c41b93d4a63d62e229d1c92584c4f4 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp @@ -47,11 +47,11 @@ //===----------------------------------------------------------------------===// #include "AST.h" -#include "Logger.h" #include "ParsedAST.h" #include "Selection.h" #include "SourceCode.h" #include "refactor/Tweak.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp index cf38227c29d7e23f3d61a76fae43e166459b7eb9..69bfe67314185c478ba6d86503f1e1791456cdd7 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp @@ -5,12 +5,12 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "Logger.h" #include "ParsedAST.h" #include "Protocol.h" #include "Selection.h" #include "SourceCode.h" #include "refactor/Tweak.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp b/clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp index 62a306c9316d5d1a3005dcc1b554d0112df0b370..2534cf562daa89461c91c6f397afec987c62def5 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp @@ -6,10 +6,10 @@ // //===----------------------------------------------------------------------===// -#include "Logger.h" #include "ParsedAST.h" #include "SourceCode.h" #include "refactor/Tweak.h" +#include "support/Logger.h" #include "clang/AST/ExprObjC.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/RawStringLiteral.cpp b/clang-tools-extra/clangd/refactor/tweaks/RawStringLiteral.cpp index c5f480cacd760c1c303830ea48f2f45e02ce70b9..bec45be6c32541eec824e25665937ef19dba5a79 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/RawStringLiteral.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/RawStringLiteral.cpp @@ -5,10 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "Logger.h" #include "ParsedAST.h" #include "SourceCode.h" #include "refactor/Tweak.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" diff --git a/clang-tools-extra/clangd/refactor/tweaks/SwapIfBranches.cpp b/clang-tools-extra/clangd/refactor/tweaks/SwapIfBranches.cpp index 1d57cd5c7132060d8195560a1841a452037560f4..2422743019a1328b629686681cbc5b5b0cad7a88 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/SwapIfBranches.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/SwapIfBranches.cpp @@ -5,10 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "Logger.h" #include "ParsedAST.h" #include "SourceCode.h" #include "refactor/Tweak.h" +#include "support/Logger.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" diff --git a/clang-tools-extra/clangd/support/CMakeLists.txt b/clang-tools-extra/clangd/support/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..719d7577576d332f5162858c4f4a1478f5d46fcf --- /dev/null +++ b/clang-tools-extra/clangd/support/CMakeLists.txt @@ -0,0 +1,31 @@ +# clangd/support contains low-level support libraries that do not depend +# on clang either programmatically or conceptually. + +set(LLVM_LINK_COMPONENTS + Support + ) + +if(CLANG_BUILT_STANDALONE) + # needed to get HAVE_CXX_ATOMICS64_WITHOUT_LIB defined + include(CheckAtomic) +endif() + +set(CLANGD_ATOMIC_LIB "") +if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB OR NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) + list(APPEND CLANGD_ATOMIC_LIB "atomic") +endif() + +include_directories(..) +add_clang_library(clangdSupport + Cancellation.cpp + Context.cpp + FSProvider.cpp + Logger.cpp + Shutdown.cpp + Threading.cpp + Trace.cpp + + LINK_LIBS + ${LLVM_PTHREAD_LIB} + ${CLANGD_ATOMIC_LIB} + ) diff --git a/clang-tools-extra/clangd/Cancellation.cpp b/clang-tools-extra/clangd/support/Cancellation.cpp similarity index 97% rename from clang-tools-extra/clangd/Cancellation.cpp rename to clang-tools-extra/clangd/support/Cancellation.cpp index 2120e700e7198c290b6a10036c1d594b5dbeb1bf..d544c17e279c7e7e15a0f957d1468f275a463349 100644 --- a/clang-tools-extra/clangd/Cancellation.cpp +++ b/clang-tools-extra/clangd/support/Cancellation.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "Cancellation.h" +#include "support/Cancellation.h" #include namespace clang { diff --git a/clang-tools-extra/clangd/Cancellation.h b/clang-tools-extra/clangd/support/Cancellation.h similarity index 96% rename from clang-tools-extra/clangd/Cancellation.h rename to clang-tools-extra/clangd/support/Cancellation.h index 0bee6f355c39a3288910269912c5e32d20751768..f33b0b5c6763561f1c33d56493c9cd5a201880bd 100644 --- a/clang-tools-extra/clangd/Cancellation.h +++ b/clang-tools-extra/clangd/support/Cancellation.h @@ -54,10 +54,10 @@ // Measuring the start -> cancel -> acknowledge -> finish timeline would // help find where libraries' cancellation should be improved. -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CANCELLATION_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CANCELLATION_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_CANCELLATION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_CANCELLATION_H -#include "Context.h" +#include "support/Context.h" #include "llvm/Support/Error.h" #include #include diff --git a/clang-tools-extra/clangd/Context.cpp b/clang-tools-extra/clangd/support/Context.cpp similarity index 97% rename from clang-tools-extra/clangd/Context.cpp rename to clang-tools-extra/clangd/support/Context.cpp index 8e8bba6e97a863523cb3f72fb9a0b10c2d7c58a0..266dd003f8f6e110eb8606d7bf91dc2bb5b5cd02 100644 --- a/clang-tools-extra/clangd/Context.cpp +++ b/clang-tools-extra/clangd/support/Context.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "Context.h" +#include "support/Context.h" #include namespace clang { diff --git a/clang-tools-extra/clangd/Context.h b/clang-tools-extra/clangd/support/Context.h similarity index 93% rename from clang-tools-extra/clangd/Context.h rename to clang-tools-extra/clangd/support/Context.h index 71aeaba95254d1b9c4df41119d33819b6ee775d6..894032bdd88386d75e62df0f31ae4a1b713e5110 100644 --- a/clang-tools-extra/clangd/Context.h +++ b/clang-tools-extra/clangd/support/Context.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONTEXT_H_ -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONTEXT_H_ +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_CONTEXT_H_ +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_CONTEXT_H_ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" @@ -120,20 +120,20 @@ public: template Context derive(const Key &Key, typename std::decay::type Value) const & { - return Context(std::make_shared(Data{ - /*Parent=*/DataPtr, &Key, - std::make_unique::type>>( - std::move(Value))})); + return Context(std::make_shared( + Data{/*Parent=*/DataPtr, &Key, + std::make_unique::type>>( + std::move(Value))})); } template Context derive(const Key &Key, typename std::decay::type Value) && /* takes ownership */ { - return Context(std::make_shared(Data{ - /*Parent=*/std::move(DataPtr), &Key, - std::make_unique::type>>( - std::move(Value))})); + return Context(std::make_shared( + Data{/*Parent=*/std::move(DataPtr), &Key, + std::make_unique::type>>( + std::move(Value))})); } /// Derives a child context, using an anonymous key. @@ -219,4 +219,4 @@ private: } // namespace clangd } // namespace clang -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONTEXT_H_ +#endif diff --git a/clang-tools-extra/clangd/FSProvider.cpp b/clang-tools-extra/clangd/support/FSProvider.cpp similarity index 98% rename from clang-tools-extra/clangd/FSProvider.cpp rename to clang-tools-extra/clangd/support/FSProvider.cpp index 80d6be005cc41941e36fa41e5c4aa5cc8654d05f..6474a3c4a3650ee4878206ce41ebd2b2f8fbd1a9 100644 --- a/clang-tools-extra/clangd/FSProvider.cpp +++ b/clang-tools-extra/clangd/support/FSProvider.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "FSProvider.h" +#include "support/FSProvider.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" diff --git a/clang-tools-extra/clangd/FSProvider.h b/clang-tools-extra/clangd/support/FSProvider.h similarity index 91% rename from clang-tools-extra/clangd/FSProvider.h rename to clang-tools-extra/clangd/support/FSProvider.h index 1fe3ba864a33d8b702ebc0c052905ba41dc41d45..a53a4149a47b8b47a4ec75d7238a0878a7577cba 100644 --- a/clang-tools-extra/clangd/FSProvider.h +++ b/clang-tools-extra/clangd/support/FSProvider.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FSPROVIDER_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FSPROVIDER_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FSPROVIDER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FSPROVIDER_H #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/VirtualFileSystem.h" diff --git a/clang-tools-extra/clangd/Function.h b/clang-tools-extra/clangd/support/Function.h similarity index 96% rename from clang-tools-extra/clangd/Function.h rename to clang-tools-extra/clangd/support/Function.h index cfcb4a550a765fcd07fc35de483e7c2c0d514193..2cac1b1e7f67e441963dd81d66cb29a3b19675a9 100644 --- a/clang-tools-extra/clangd/Function.h +++ b/clang-tools-extra/clangd/support/Function.h @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FUNCTION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FUNCTION_H #include "llvm/ADT/FunctionExtras.h" #include "llvm/Support/Error.h" diff --git a/clang-tools-extra/clangd/Logger.cpp b/clang-tools-extra/clangd/support/Logger.cpp similarity index 96% rename from clang-tools-extra/clangd/Logger.cpp rename to clang-tools-extra/clangd/support/Logger.cpp index 7b8c9a3e6ffc05084ef78ee1fdaaf6431e17c8b1..768d2e52210b24b0ebf90f03cefd2a996e85fa29 100644 --- a/clang-tools-extra/clangd/Logger.cpp +++ b/clang-tools-extra/clangd/support/Logger.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "Logger.h" -#include "Trace.h" +#include "support/Logger.h" +#include "support/Trace.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang-tools-extra/clangd/Logger.h b/clang-tools-extra/clangd/support/Logger.h similarity index 97% rename from clang-tools-extra/clangd/Logger.h rename to clang-tools-extra/clangd/support/Logger.h index 7a5d5140d4824f8671a6912cbc7a30a49fd252de..72d1408bdc77cfaf1675254d1b26a4ab5f7aa280 100644 --- a/clang-tools-extra/clangd/Logger.h +++ b/clang-tools-extra/clangd/support/Logger.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_LOGGER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_LOGGER_H #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" diff --git a/clang-tools-extra/clangd/Path.h b/clang-tools-extra/clangd/support/Path.h similarity index 87% rename from clang-tools-extra/clangd/Path.h rename to clang-tools-extra/clangd/support/Path.h index eaa72245042506f6b95054d69c700e1ba564f6af..4d4ad7f490473290c23004340fe3685e9425a5d6 100644 --- a/clang-tools-extra/clangd/Path.h +++ b/clang-tools-extra/clangd/support/Path.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATH_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATH_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_PATH_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_PATH_H #include "llvm/ADT/StringRef.h" #include diff --git a/clang-tools-extra/clangd/Shutdown.cpp b/clang-tools-extra/clangd/support/Shutdown.cpp similarity index 91% rename from clang-tools-extra/clangd/Shutdown.cpp rename to clang-tools-extra/clangd/support/Shutdown.cpp index 36d977570a4fe768119507d5d85027e1186bcafe..7ce01ee171e872f8097aac459d893073cd80d444 100644 --- a/clang-tools-extra/clangd/Shutdown.cpp +++ b/clang-tools-extra/clangd/support/Shutdown.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "Shutdown.h" +#include "support/Shutdown.h" #include #include @@ -31,10 +31,7 @@ void requestShutdown() { std::abort(); } -bool shutdownRequested() { - return ShutdownRequested; -} +bool shutdownRequested() { return ShutdownRequested; } } // namespace clangd } // namespace clang - diff --git a/clang-tools-extra/clangd/Shutdown.h b/clang-tools-extra/clangd/support/Shutdown.h similarity index 96% rename from clang-tools-extra/clangd/Shutdown.h rename to clang-tools-extra/clangd/support/Shutdown.h index 94ada3171f319efc8add0ec0c821eca3218cc04f..896e1521fe6a1943e57976025501c40eb8c67c88 100644 --- a/clang-tools-extra/clangd/Shutdown.h +++ b/clang-tools-extra/clangd/support/Shutdown.h @@ -40,8 +40,8 @@ // returns an error, etc. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SHUTDOWN_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SHUTDOWN_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_SHUTDOWN_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_SHUTDOWN_H #include #include diff --git a/clang-tools-extra/clangd/Threading.cpp b/clang-tools-extra/clangd/support/Threading.cpp similarity index 93% rename from clang-tools-extra/clangd/Threading.cpp rename to clang-tools-extra/clangd/support/Threading.cpp index a651b70f02a6ffbbd183062dd11ccedb97e2b52a..5f95888ae3e2d7ce2bbe42651131bd0d794b2344 100644 --- a/clang-tools-extra/clangd/Threading.cpp +++ b/clang-tools-extra/clangd/support/Threading.cpp @@ -1,6 +1,5 @@ -#include "Threading.h" -#include "Trace.h" -#include "clang/Basic/Stack.h" +#include "support/Threading.h" +#include "support/Trace.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Threading.h" @@ -10,7 +9,7 @@ #include #elif defined(__APPLE__) #include -#elif defined (_WIN32) +#elif defined(_WIN32) #include #endif @@ -96,7 +95,8 @@ void AsyncTaskRunner::runAsync(const llvm::Twine &Name, }; // Ensure our worker threads have big enough stacks to run clang. - llvm::llvm_execute_on_thread_async(std::move(Task), clang::DesiredStackSize); + llvm::llvm_execute_on_thread_async(std::move(Task), + /*clang::DesiredStackSize*/ 8 << 20); } Deadline timeoutSeconds(llvm::Optional Seconds) { diff --git a/clang-tools-extra/clangd/Threading.h b/clang-tools-extra/clangd/support/Threading.h similarity index 96% rename from clang-tools-extra/clangd/Threading.h rename to clang-tools-extra/clangd/support/Threading.h index 878069f3b9ee82f167144e7000630103c9992802..310dd7bc5a24668f188c79decbc6dec1ef154215 100644 --- a/clang-tools-extra/clangd/Threading.h +++ b/clang-tools-extra/clangd/support/Threading.h @@ -6,10 +6,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_THREADING_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_THREADING_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADING_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADING_H -#include "Context.h" +#include "support/Context.h" #include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/Twine.h" #include diff --git a/clang-tools-extra/clangd/Trace.cpp b/clang-tools-extra/clangd/support/Trace.cpp similarity index 98% rename from clang-tools-extra/clangd/Trace.cpp rename to clang-tools-extra/clangd/support/Trace.cpp index 5bcbf221c4351f1c40ac1f63e1b0b928224a05f1..b880a5b3411d4ea7c8d6fad176501a1e38cd8bf5 100644 --- a/clang-tools-extra/clangd/Trace.cpp +++ b/clang-tools-extra/clangd/support/Trace.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "Trace.h" -#include "Context.h" +#include "support/Trace.h" +#include "support/Context.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/Chrono.h" @@ -149,10 +149,10 @@ private: void rawEvent(llvm::StringRef Phase, const llvm::json::Object &Event) /*REQUIRES(Mu)*/ { // PID 0 represents the clangd process. - Out.object([&]{ + Out.object([&] { Out.attribute("pid", 0); Out.attribute("ph", Phase); - for (const auto& KV : Event) + for (const auto &KV : Event) Out.attribute(KV.first, KV.second); }); } diff --git a/clang-tools-extra/clangd/Trace.h b/clang-tools-extra/clangd/support/Trace.h similarity index 96% rename from clang-tools-extra/clangd/Trace.h rename to clang-tools-extra/clangd/support/Trace.h index 55dc0ef0580c1fe3852515c69ab36c9b4e516f19..e2c91eb4f100cbe490518d78b9dcd0e1fd16ed37 100644 --- a/clang-tools-extra/clangd/Trace.h +++ b/clang-tools-extra/clangd/support/Trace.h @@ -14,10 +14,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_ -#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_ +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_TRACE_H_ +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_TRACE_H_ -#include "Context.h" +#include "support/Context.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/JSON.h" #include "llvm/Support/raw_ostream.h" @@ -104,4 +104,4 @@ private: } // namespace clangd } // namespace clang -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_ +#endif diff --git a/clang-tools-extra/clangd/test/dependency-output.test b/clang-tools-extra/clangd/test/dependency-output.test new file mode 100644 index 0000000000000000000000000000000000000000..ed289bbcdbe448bf73c07ec86bdb29b38760d5ec --- /dev/null +++ b/clang-tools-extra/clangd/test/dependency-output.test @@ -0,0 +1,13 @@ +# UNSUPPORTED: windows-gnu,windows-msvc +# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +--- +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabaseChanges":{"/clangd-test/foo.c": +{"workingDirectory":"/clangd-test", "compilationCommand": ["clang", "-c", "-Xclang", "--show-includes", "-Xclang", "-sys-header-deps", "foo.c"]}}}}} +--- +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"cpp","version":1,"text":"int a;\n#include "}}} +#CHECK-NOT: Note: including file +--- +{"jsonrpc":"2.0","id":3,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/tool/CMakeLists.txt b/clang-tools-extra/clangd/tool/CMakeLists.txt index b81f90a23b787e6150cb68ba339b05df72de63b1..3368013f50798cbd4663414fc3a5b1252845caf9 100644 --- a/clang-tools-extra/clangd/tool/CMakeLists.txt +++ b/clang-tools-extra/clangd/tool/CMakeLists.txt @@ -32,5 +32,6 @@ target_link_libraries(clangd PRIVATE clangTidy clangDaemon + clangdSupport ${CLANGD_XPC_LIBS} ) diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 92e46a662953ed73db9f3f51e97c6783983649ca..575722e232c9d5e86291071ab5bb712cf8e7af71 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -9,15 +9,15 @@ #include "ClangdLSPServer.h" #include "CodeComplete.h" #include "Features.inc" -#include "Path.h" #include "PathMapping.h" #include "Protocol.h" -#include "Shutdown.h" -#include "Trace.h" #include "Transport.h" #include "index/Background.h" #include "index/Serialization.h" #include "refactor/Rename.h" +#include "support/Path.h" +#include "support/Shutdown.h" +#include "support/Trace.h" #include "clang/Basic/Version.h" #include "clang/Format/Format.h" #include "llvm/ADT/Optional.h" diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index 4119445b85a05d6d61fd055c3e3d130497b602d0..962a8785ce8dd4ad75860a3afac827704f6ec20a 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -27,7 +27,6 @@ add_unittest(ClangdUnitTests ClangdTests Annotations.cpp ASTTests.cpp BackgroundIndexTests.cpp - CancellationTests.cpp CanonicalIncludesTests.cpp ClangdTests.cpp ClangdLSPServerTests.cpp @@ -35,7 +34,6 @@ add_unittest(ClangdUnitTests ClangdTests CodeCompletionStringsTests.cpp CollectMacrosTests.cpp CompileCommandsTests.cpp - ContextTests.cpp DexTests.cpp DiagnosticsTests.cpp DraftStoreTests.cpp @@ -47,7 +45,6 @@ add_unittest(ClangdUnitTests ClangdTests FormattedStringTests.cpp FormatTests.cpp FSTests.cpp - FunctionTests.cpp FuzzyMatchTests.cpp GlobalCompilationDatabaseTests.cpp HeadersTests.cpp @@ -76,14 +73,18 @@ add_unittest(ClangdUnitTests ClangdTests TestFS.cpp TestIndex.cpp TestTU.cpp - ThreadingTests.cpp - TraceTests.cpp TypeHierarchyTests.cpp TweakTests.cpp TweakTesting.cpp URITests.cpp XRefsTests.cpp + support/CancellationTests.cpp + support/ContextTests.cpp + support/FunctionTests.cpp + support/ThreadingTests.cpp + support/TraceTests.cpp + $ ) @@ -107,6 +108,7 @@ clang_target_link_libraries(ClangdTests target_link_libraries(ClangdTests PRIVATE clangDaemon + clangdSupport clangTidy LLVMSupport LLVMTestingSupport diff --git a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp index 5f169fefd3bd08339728c15e31d31f88a53e1a2e..aa65a2eb521db426fdfc25aa8dcc37f86a022207 100644 --- a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp @@ -10,10 +10,10 @@ #include "ClangdLSPServer.h" #include "CodeComplete.h" #include "LSPClient.h" -#include "Logger.h" #include "Protocol.h" #include "TestFS.h" #include "refactor/Rename.h" +#include "support/Logger.h" #include "llvm/Support/JSON.h" #include "llvm/Testing/Support/SupportHelpers.h" #include "gmock/gmock.h" diff --git a/clang-tools-extra/clangd/unittests/ClangdTests.cpp b/clang-tools-extra/clangd/unittests/ClangdTests.cpp index 8bb4cad52dbacc0099c98668e751cff1aa50881a..81075ff1bbe7324cda9b152b06fd9de8de56941a 100644 --- a/clang-tools-extra/clangd/unittests/ClangdTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdTests.cpp @@ -14,8 +14,8 @@ #include "Matchers.h" #include "SyncAPI.h" #include "TestFS.h" -#include "Threading.h" #include "URI.h" +#include "support/Threading.h" #include "clang/Config/config.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "llvm/ADT/SmallVector.h" diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 47637024ab91583d1bfda96135509643b0085299..d8926d4fd3f53e7aafd14d6dff516c71726125eb 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -18,9 +18,9 @@ #include "TestFS.h" #include "TestIndex.h" #include "TestTU.h" -#include "Threading.h" #include "index/Index.h" #include "index/MemIndex.h" +#include "support/Threading.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/Error.h" diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp index fc98b56de2d6755e4f4c902e2f1cb721377aff0f..cad9872916234b13807ae6a12922e6f505057b35 100644 --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -79,6 +79,20 @@ TEST(CommandMangler, StripOutput) { EXPECT_THAT(Cmd, Not(Contains(Stripped))); } +TEST(CommandMangler, StripShowIncludes) { + auto Mangler = CommandMangler::forTests(); + std::vector Cmd = {"clang-cl", "/showIncludes", "foo.cc"}; + Mangler.adjust(Cmd); + EXPECT_THAT(Cmd, Not(Contains("/showIncludes"))); +} + +TEST(CommandMangler, StripShowIncludesUser) { + auto Mangler = CommandMangler::forTests(); + std::vector Cmd = {"clang-cl", "/showIncludes:user", "foo.cc"}; + Mangler.adjust(Cmd); + EXPECT_THAT(Cmd, Not(Contains("/showIncludes:user"))); +} + TEST(CommandMangler, ClangPath) { auto Mangler = CommandMangler::forTests(); Mangler.ClangPath = testPath("fake/clang"); diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 026e145ed65deee89600fa47d340cedb46eb8bf9..90d3621286db1df688b309f9d0701de905990e1b 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -9,13 +9,13 @@ #include "Annotations.h" #include "Diagnostics.h" #include "ParsedAST.h" -#include "Path.h" #include "Protocol.h" #include "SourceCode.h" #include "TestFS.h" #include "TestIndex.h" #include "TestTU.h" #include "index/MemIndex.h" +#include "support/Path.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticSema.h" #include "llvm/Support/ScopedPrinter.h" @@ -272,6 +272,33 @@ TEST(DiagnosticsTest, ClangTidy) { "use a trailing return type for this function"))))); } +TEST(DiagnosticTest, NoMultipleDiagnosticInFlight) { + Annotations Main(R"cpp( + template struct Foo { + T *begin(); + T *end(); + }; + struct LabelInfo { + int a; + bool b; + }; + + void f() { + Foo label_info_map; + [[for]] (auto it = label_info_map.begin(); it != label_info_map.end(); ++it) { + auto S = *it; + } + } + )cpp"); + TestTU TU = TestTU::withCode(Main.code()); + TU.ClangTidyChecks = "modernize-loop-convert"; + EXPECT_THAT( + TU.build().getDiagnostics(), + UnorderedElementsAre(::testing::AllOf( + Diag(Main.range(), "use range-based for loop instead"), + DiagSource(Diag::ClangTidy), DiagName("modernize-loop-convert")))); +} + TEST(DiagnosticTest, ClangTidySuppressionComment) { Annotations Main(R"cpp( int main() { diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index f943772e052e38bacb47872cdb6082e3d4fb644f..03cdc02fbb18ef07ed3254d6b5c0aff65874ca1b 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -1286,6 +1286,20 @@ TEST_F(FindExplicitReferencesTest, All) { "1: targets = {}\n" "2: targets = {T}\n" }, + // unknown template name should not crash. + {R"cpp( + template