diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1576,6 +1576,7 @@ /// naturally when placed inline with the code. std::string label; }; +const char *toString(InlayHintKind); llvm::json::Value toJSON(const InlayHint &); bool operator==(const InlayHint &, const InlayHint &); bool operator<(const InlayHint &, const InlayHint &); diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1316,7 +1316,7 @@ return O && O.map("textDocument", R.textDocument) && O.map("range", R.range); } -llvm::json::Value toJSON(InlayHintKind K) { +const char *toString(InlayHintKind K) { switch (K) { case InlayHintKind::ParameterHint: return "parameter"; @@ -1328,6 +1328,8 @@ llvm_unreachable("Unknown clang.clangd.InlayHintKind"); } +llvm::json::Value toJSON(InlayHintKind K) { return toString(K); } + llvm::json::Value toJSON(const InlayHint &H) { return llvm::json::Object{{"position", H.position}, {"range", H.range}, diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -30,8 +30,10 @@ #include "Config.h" #include "GlobalCompilationDatabase.h" #include "Hover.h" +#include "InlayHints.h" #include "ParsedAST.h" #include "Preamble.h" +#include "Protocol.h" #include "SourceCode.h" #include "XRefs.h" #include "index/CanonicalIncludes.h" @@ -190,10 +192,20 @@ return true; } + // Build Inlay Hints for the entire AST or the specified range + bool buildInlayHints(llvm::Optional LineRange) { + log("Building inlay hints"); + auto Hints = inlayHints(*AST, LineRange); + + for (const auto &Hint : Hints) { + vlog(" {0} {1} {2}", toString(Hint.kind), Hint.position, Hint.label); + } + return true; + } + // Run AST-based features at each token in the file. - void testLocationFeatures( - llvm::function_ref ShouldCheckLine, - const bool EnableCodeCompletion) { + void testLocationFeatures(llvm::Optional LineRange, + const bool EnableCodeCompletion) { trace::Span Trace("testLocationFeatures"); log("Testing features at each token (may be slow in large files)"); auto &SM = AST->getSourceManager(); @@ -207,7 +219,7 @@ unsigned End = Start + Tok.length(); Position Pos = offsetToPosition(Inputs.Contents, Start); - if (!ShouldCheckLine(Pos)) + if (LineRange && LineRange->contains(Pos)) continue; trace::Span Trace("Token"); @@ -254,8 +266,7 @@ } // namespace -bool check(llvm::StringRef File, - llvm::function_ref ShouldCheckLine, +bool check(llvm::StringRef File, llvm::Optional LineRange, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion) { llvm::SmallString<0> FakeFile; @@ -282,9 +293,9 @@ : /*Don't turn on local configs for an arbitrary temp path.*/ "")); Checker C(File, Opts); if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) || - !C.buildAST()) + !C.buildAST() || !C.buildInlayHints(LineRange)) return false; - C.testLocationFeatures(ShouldCheckLine, EnableCodeCompletion); + C.testLocationFeatures(LineRange, EnableCodeCompletion); log("All checks completed, {0} errors", C.ErrCount); return C.ErrCount == 0; diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -61,8 +61,7 @@ namespace clangd { // Implemented in Check.cpp. -bool check(const llvm::StringRef File, - llvm::function_ref ShouldCheckLine, +bool check(const llvm::StringRef File, llvm::Optional LineRange, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion); @@ -955,8 +954,9 @@ return 1; } log("Entering check mode (no LSP server)"); - uint32_t Begin = 0, End = std::numeric_limits::max(); + llvm::Optional CheckLineRange; if (!CheckFileLines.empty()) { + uint32_t Begin = 0, End = std::numeric_limits::max(); StringRef RangeStr(CheckFileLines); bool ParseError = RangeStr.consumeInteger(0, Begin); if (RangeStr.empty()) { @@ -965,19 +965,18 @@ ParseError |= !RangeStr.consume_front("-"); ParseError |= RangeStr.consumeInteger(0, End); } - if (ParseError || !RangeStr.empty()) { - elog("Invalid --check-line specified. Use Begin-End format, e.g. 3-17"); + if (ParseError || !RangeStr.empty() || Begin <= 0 || End < Begin) { + elog( + "Invalid --check-lines specified. Use Begin-End format, e.g. 3-17"); return 1; } + CheckLineRange = Range{Position{static_cast(Begin - 1), 0}, + Position{static_cast(End), 0}}; } - auto ShouldCheckLine = [&](const Position &Pos) { - uint32_t Line = Pos.line + 1; // Position::line is 0-based. - return Line >= Begin && Line <= End; - }; // For now code completion is enabled any time the range is limited via // --check-lines. If it turns out to be to slow, we can introduce a // dedicated flag for that instead. - return check(Path, ShouldCheckLine, TFS, Opts, + return check(Path, CheckLineRange, TFS, Opts, /*EnableCodeCompletion=*/!CheckFileLines.empty()) ? 0 : static_cast(ErrorResultCode::CheckFailed);