Skip to content

Commit

Permalink
[clangd] Output inlay hints with clangd --check
Browse files Browse the repository at this point in the history
With the addition of inlay hints to clangd, it would be useful to output them during verbose `clangd --check`.
This patch adds an output step for inlay hints and unifies the way `--check-lines` are passed around

Reviewed By: nridge

Differential Revision: https://reviews.llvm.org/D124344
  • Loading branch information
upsj authored and HighCommander4 committed Apr 27, 2022
1 parent a910337 commit 56058b9
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 18 deletions.
9 changes: 8 additions & 1 deletion clang-tools-extra/clangd/Protocol.cpp
Expand Up @@ -15,6 +15,7 @@
#include "support/Logger.h"
#include "clang/Basic/LLVM.h"
#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/JSON.h"
Expand Down Expand Up @@ -1318,7 +1319,7 @@ bool fromJSON(const llvm::json::Value &Params, InlayHintsParams &R,
return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);
}

llvm::json::Value toJSON(InlayHintKind K) {
static llvm::StringLiteral toString(InlayHintKind K) {
switch (K) {
case InlayHintKind::ParameterHint:
return "parameter";
Expand All @@ -1330,6 +1331,8 @@ llvm::json::Value toJSON(InlayHintKind K) {
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},
Expand All @@ -1345,6 +1348,10 @@ bool operator<(const InlayHint &A, const InlayHint &B) {
std::tie(B.position, B.range, B.kind, B.label);
}

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) {
return OS << toString(Kind);
}

static const char *toString(OffsetEncoding OE) {
switch (OE) {
case OffsetEncoding::UTF8:
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clangd/Protocol.h
Expand Up @@ -1579,6 +1579,7 @@ struct InlayHint {
llvm::json::Value toJSON(const InlayHint &);
bool operator==(const InlayHint &, const InlayHint &);
bool operator<(const InlayHint &, const InlayHint &);
llvm::raw_ostream &operator<<(llvm::raw_ostream &, InlayHintKind);

struct ReferenceContext {
/// Include the declaration of the current symbol.
Expand Down
25 changes: 18 additions & 7 deletions clang-tools-extra/clangd/tool/Check.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -190,10 +192,19 @@ class Checker {
return true;
}

// Build Inlay Hints for the entire AST or the specified range
void buildInlayHints(llvm::Optional<Range> LineRange) {
log("Building inlay hints");
auto Hints = inlayHints(*AST, LineRange);

for (const auto &Hint : Hints) {
vlog(" {0} {1} {2}", Hint.kind, Hint.position, Hint.label);
}
}

// Run AST-based features at each token in the file.
void testLocationFeatures(
llvm::function_ref<bool(const Position &)> ShouldCheckLine,
const bool EnableCodeCompletion) {
void testLocationFeatures(llvm::Optional<Range> LineRange,
const bool EnableCodeCompletion) {
trace::Span Trace("testLocationFeatures");
log("Testing features at each token (may be slow in large files)");
auto &SM = AST->getSourceManager();
Expand All @@ -207,7 +218,7 @@ class Checker {
unsigned End = Start + Tok.length();
Position Pos = offsetToPosition(Inputs.Contents, Start);

if (!ShouldCheckLine(Pos))
if (LineRange && !LineRange->contains(Pos))
continue;

trace::Span Trace("Token");
Expand Down Expand Up @@ -254,8 +265,7 @@ class Checker {

} // namespace

bool check(llvm::StringRef File,
llvm::function_ref<bool(const Position &)> ShouldCheckLine,
bool check(llvm::StringRef File, llvm::Optional<Range> LineRange,
const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts,
bool EnableCodeCompletion) {
llvm::SmallString<0> FakeFile;
Expand Down Expand Up @@ -284,7 +294,8 @@ bool check(llvm::StringRef File,
if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) ||
!C.buildAST())
return false;
C.testLocationFeatures(ShouldCheckLine, EnableCodeCompletion);
C.buildInlayHints(LineRange);
C.testLocationFeatures(LineRange, EnableCodeCompletion);

log("All checks completed, {0} errors", C.ErrCount);
return C.ErrCount == 0;
Expand Down
19 changes: 9 additions & 10 deletions clang-tools-extra/clangd/tool/ClangdMain.cpp
Expand Up @@ -61,8 +61,7 @@ namespace clang {
namespace clangd {

// Implemented in Check.cpp.
bool check(const llvm::StringRef File,
llvm::function_ref<bool(const Position &)> ShouldCheckLine,
bool check(const llvm::StringRef File, llvm::Optional<Range> LineRange,
const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts,
bool EnableCodeCompletion);

Expand Down Expand Up @@ -955,8 +954,9 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
return 1;
}
log("Entering check mode (no LSP server)");
uint32_t Begin = 0, End = std::numeric_limits<uint32_t>::max();
llvm::Optional<Range> CheckLineRange;
if (!CheckFileLines.empty()) {
uint32_t Begin = 0, End = std::numeric_limits<uint32_t>::max();
StringRef RangeStr(CheckFileLines);
bool ParseError = RangeStr.consumeInteger(0, Begin);
if (RangeStr.empty()) {
Expand All @@ -965,19 +965,18 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
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<int>(Begin - 1), 0},
Position{static_cast<int>(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<int>(ErrorResultCode::CheckFailed);
Expand Down

0 comments on commit 56058b9

Please sign in to comment.