VitaNuo updated this revision to Diff 509633.
VitaNuo added a comment.
Use custom command.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D144862/new/
https://reviews.llvm.org/D144862
Files:
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/ClangdLSPServer.h
clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/ClangdServer.h
clang-tools-extra/clangd/Protocol.cpp
clang-tools-extra/clangd/Protocol.h
clang-tools-extra/clangd/XRefs.cpp
clang-tools-extra/clangd/XRefs.h
clang-tools-extra/clangd/test/code-action-request.test
clang-tools-extra/clangd/test/fixits-command.test
clang-tools-extra/clangd/test/initialize-params.test
Index: clang-tools-extra/clangd/test/initialize-params.test
===================================================================
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -9,6 +9,7 @@
# CHECK-NEXT: "callHierarchyProvider": true,
# CHECK-NEXT: "clangdInlayHintsProvider": true,
# CHECK-NEXT: "codeActionProvider": true,
+# CHECK-NEXT: "codeLensProvider": true,
# CHECK-NEXT: "compilationDatabase": {
# CHECK-NEXT: "automaticReload": true
# CHECK-NEXT: },
Index: clang-tools-extra/clangd/test/fixits-command.test
===================================================================
--- clang-tools-extra/clangd/test/fixits-command.test
+++ clang-tools-extra/clangd/test/fixits-command.test
@@ -63,7 +63,8 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
-# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: null
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: place parentheses around the assignment to silence this warning"
@@ -88,7 +89,8 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
-# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: null
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: use '==' to turn this assignment into an equality comparison"
@@ -133,7 +135,8 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
-# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: null
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: place parentheses around the assignment to silence this warning"
@@ -158,7 +161,8 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
-# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: null
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: use '==' to turn this assignment into an equality comparison"
Index: clang-tools-extra/clangd/test/code-action-request.test
===================================================================
--- clang-tools-extra/clangd/test/code-action-request.test
+++ clang-tools-extra/clangd/test/code-action-request.test
@@ -44,7 +44,8 @@
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: "tweakID": "ExpandDeducedType"
-# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: null
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyTweak",
# CHECK-NEXT: "title": "Replace with deduced type"
Index: clang-tools-extra/clangd/XRefs.h
===================================================================
--- clang-tools-extra/clangd/XRefs.h
+++ clang-tools-extra/clangd/XRefs.h
@@ -32,6 +32,8 @@
namespace clangd {
class ParsedAST;
+std::vector<CodeLens> findCodeLens(ParsedAST &AST);
+
// Describes where a symbol is declared and defined (as far as clangd knows).
// There are three cases:
// - a declaration only, no definition is known (e.g. only header seen)
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -10,12 +10,15 @@
#include "FindSymbols.h"
#include "FindTarget.h"
#include "HeuristicResolver.h"
+#include "IncludeCleaner.h"
#include "ParsedAST.h"
#include "Protocol.h"
#include "Quality.h"
#include "Selection.h"
#include "SourceCode.h"
#include "URI.h"
+#include "clang-include-cleaner/Analysis.h"
+#include "clang-include-cleaner/Types.h"
#include "index/Index.h"
#include "index/Merge.h"
#include "index/Relation.h"
@@ -51,6 +54,7 @@
#include "clang/Tooling/Syntax/Tokens.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallSet.h"
@@ -61,6 +65,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
+#include <string>
#include <vector>
namespace clang {
@@ -1312,8 +1317,67 @@
}
} // namespace
+std::vector<CodeLens> findCodeLens(ParsedAST &AST) {
+ const auto &SM = AST.getSourceManager();
+ std::vector<CodeLens> Result;
+ auto Includes = AST.getIncludeStructure().MainFileIncludes;
+ auto ConvertedMainFileIncludes = convertIncludes(SM, Includes);
+ for (auto &Inc : Includes) {
+ llvm::DenseSet<include_cleaner::Symbol> UsedSyms;
+ auto AnalyzedInclude = convertIncludes(SM, Inc);
+ include_cleaner::walkUsed(
+ AST.getLocalTopLevelDecls(), collectMacroReferences(AST),
+ AST.getPragmaIncludes(), SM,
+ [&](const include_cleaner::SymbolReference &Ref,
+ llvm::ArrayRef<include_cleaner::Header> Providers) {
+ if (Ref.RT != include_cleaner::RefType::Explicit)
+ return;
+
+ for (const auto &H : Providers) {
+ auto MatchingIncludes = ConvertedMainFileIncludes.match(H);
+ // No match for this provider in the main file.
+ if (MatchingIncludes.empty())
+ continue;
+
+ // Check if the referenced include matches this provider.
+ if (!AnalyzedInclude.match(H).empty()) {
+ UsedSyms.insert(Ref.Target);
+ }
+
+ // Don't look for rest of the providers once we've found a match
+ // in the main file.
+ break;
+ }
+ });
+
+ // Compute the length of the #include line
+ auto IncludeLen =
+ std::string{"#include"}.length() + Inc.Written.length() + 1;
+ CodeLens Lens;
+ Lens.range = clangd::Range{Position{Inc.HashLine, 0},
+ Position{Inc.HashLine, (int)IncludeLen}};
+
+ Command Cmd;
+ Cmd.title = std::to_string(UsedSyms.size()) + " used symbols";
+ Cmd.command = "clangd/findReferences";
+
+ auto MainFilePath = AST.tuPath();
+ auto URIMainFile = URIForFile::canonicalize(MainFilePath, MainFilePath);
+
+ Cmd.argument = URIMainFile;
+ Position P = sourceLocToPosition(SM, SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset));
+ Cmd.argument2 = P;
+ Lens.command = Cmd;
+ Result.push_back(Lens);
+ }
+
+ return Result;
+}
+
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
const SymbolIndex *Index, bool AddContext) {
+ llvm::errs() << "Find references for path: " << AST.tuPath() << "\n";
+ llvm::errs() << "Find references for position: " << Pos << "\n";
ReferencesResult Results;
const SourceManager &SM = AST.getSourceManager();
auto MainFilePath = AST.tuPath();
@@ -1324,6 +1388,58 @@
return {};
}
+ auto Includes = AST.getIncludeStructure().MainFileIncludes;
+ auto ConvertedMainFileIncludes = convertIncludes(SM, Includes);
+ for (auto &Inc : Includes) {
+ if (Inc.HashLine != Pos.line)
+ continue;
+
+ auto ReferencedInclude = convertIncludes(SM, Inc);
+ include_cleaner::walkUsed(
+ AST.getLocalTopLevelDecls(), collectMacroReferences(AST),
+ AST.getPragmaIncludes(), SM,
+ [&](const include_cleaner::SymbolReference &Ref,
+ llvm::ArrayRef<include_cleaner::Header> Providers) {
+ if (Ref.RT != include_cleaner::RefType::Explicit)
+ return;
+
+ auto Loc = SM.getFileLoc(Ref.RefLocation);
+ for (const auto &H : Providers) {
+ auto MatchingIncludes = ConvertedMainFileIncludes.match(H);
+ // No match for this provider in the main file.
+ if (MatchingIncludes.empty())
+ continue;
+
+ // Check if the referenced include matches this provider.
+ if (!ReferencedInclude.match(H).empty()) {
+ ReferencesResult::Reference Result;
+ auto TokLen =
+ Lexer::MeasureTokenLength(Loc, SM, AST.getLangOpts());
+ Result.Loc.range =
+ halfOpenToRange(SM, CharSourceRange::getCharRange(
+ Loc, Loc.getLocWithOffset(TokLen)));
+ Result.Loc.uri = URIMainFile;
+ Results.References.push_back(std::move(Result));
+ }
+
+ // Don't look for rest of the providers once we've found a match
+ // in the main file.
+ return;
+ }
+ });
+ if (Results.References.empty())
+ return {};
+
+ // Add the #include line to the references list.
+ auto IncludeLen =
+ std::string{"#include"}.length() + Inc.Written.length() + 1;
+ ReferencesResult::Reference Result;
+ Result.Loc.range = clangd::Range{Position{Inc.HashLine, 0},
+ Position{Inc.HashLine, (int)IncludeLen}};
+ Result.Loc.uri = URIMainFile;
+ Results.References.push_back(std::move(Result));
+ }
+
llvm::DenseSet<SymbolID> IDsToQuery, OverriddenMethods;
const auto *IdentifierAtCursor =
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -998,6 +998,7 @@
// This is `arguments?: []any` in LSP.
// All clangd's commands accept a single argument (or none => null).
llvm::json::Value argument = nullptr;
+ llvm::json::Value argument2 = nullptr;
};
bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &,
llvm::json::Path);
@@ -1876,6 +1877,23 @@
llvm::json::Value toJSON(const ASTNode &);
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ASTNode &);
+/// Parameters for the code lens request.
+struct CodeLensParams {
+ TextDocumentIdentifier textDocument;
+};
+bool fromJSON(const llvm::json::Value &, CodeLensParams &,
+ llvm::json::Path);
+
+/// Code lens response payload.
+struct CodeLens {
+ /// The range in which this code lens is valid.
+ Range range;
+ /// The command this code lens represents.
+ Command command;
+};
+llvm::json::Value toJSON(const CodeLens &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CodeLens &);
+
} // namespace clangd
} // namespace clang
Index: clang-tools-extra/clangd/Protocol.cpp
===================================================================
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -535,6 +535,23 @@
return O && O.map("textDocument", R.textDocument);
}
+bool fromJSON(const llvm::json::Value &Params, CodeLensParams &R,
+ llvm::json::Path P) {
+ llvm::json::ObjectMapper O(Params, P);
+ return O && O.map("textDocument", R.textDocument);
+}
+
+llvm::json::Value toJSON(const CodeLens &CL) {
+ return llvm::json::Object {
+ {"range", CL.range},
+ {"command", CL.command}
+ };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeLens &CL) {
+ return OS << "Code lens: " << CL.range.start << '-' << CL.range.end;
+}
+
bool fromJSON(const llvm::json::Value &Params, DidSaveTextDocumentParams &R,
llvm::json::Path P) {
llvm::json::ObjectMapper O(Params, P);
@@ -809,10 +826,10 @@
mapOptOrNull(Params, "limit", R.limit, P);
}
-llvm::json::Value toJSON(const Command &C) {
+llvm::json::Value toJSON(const Command &C) {
auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}};
if (!C.argument.getAsNull())
- Cmd["arguments"] = llvm::json::Array{C.argument};
+ Cmd["arguments"] = llvm::json::Array{C.argument, C.argument2};
return std::move(Cmd);
}
@@ -1301,8 +1318,11 @@
bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R,
llvm::json::Path P) {
TextDocumentPositionParams &Base = R;
+ bool ReferenceParamsFromJson = fromJSON(Params, Base, P);
+ llvm::errs() << "Reference params from JSON document: " << R.textDocument.uri << "\n";
+ llvm::errs() << "Reference params from JSON position: " << R.position << "\n";
llvm::json::ObjectMapper O(Params, P);
- return fromJSON(Params, Base, P) && O && O.mapOptional("context", R.context);
+ return ReferenceParamsFromJson && O && O.mapOptional("context", R.context);
}
llvm::json::Value toJSON(SymbolTag Tag) {
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -305,6 +305,9 @@
void findReferences(PathRef File, Position Pos, uint32_t Limit,
bool AddContainer, Callback<ReferencesResult> CB);
+ /// Retrieve code lenses.
+ void findCodeLens(PathRef File, Callback<std::vector<CodeLens>> CB);
+
/// Run formatting for the \p File with content \p Code.
/// If \p Rng is non-null, formats only that region.
void formatFile(PathRef File, std::optional<Range> Rng,
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -911,6 +911,17 @@
WorkScheduler->runWithAST("References", File, std::move(Action));
}
+void ClangdServer::findCodeLens(PathRef File, Callback<std::vector<CodeLens>> CB) {
+ auto Action = [CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
+ if (!InpAST)
+ return CB(InpAST.takeError());
+
+ CB(clangd::findCodeLens(InpAST->AST));
+ };
+
+ WorkScheduler->runWithAST("CodeLens", File, std::move(Action));
+}
+
void ClangdServer::symbolInfo(PathRef File, Position Pos,
Callback<std::vector<SymbolDetails>> CB) {
auto Action =
Index: clang-tools-extra/clangd/ClangdLSPServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdLSPServer.h
+++ clang-tools-extra/clangd/ClangdLSPServer.h
@@ -173,6 +173,9 @@
void onCommandApplyEdit(const WorkspaceEdit &, Callback<llvm::json::Value>);
void onCommandApplyTweak(const TweakArgs &, Callback<llvm::json::Value>);
+ /// Implement code lens.
+ void onCodeLens(const CodeLensParams &Params, Callback<std::vector<CodeLens>> Reply);
+
/// Outgoing LSP calls.
LSPBinder::OutgoingMethod<ApplyWorkspaceEditParams,
ApplyWorkspaceEditResponse>
Index: clang-tools-extra/clangd/ClangdLSPServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -586,6 +586,7 @@
{"clangdInlayHintsProvider", true},
{"inlayHintProvider", true},
{"foldingRangeProvider", true},
+ {"codeLensProvider", true},
};
{
@@ -1379,6 +1380,8 @@
void ClangdLSPServer::onReference(
const ReferenceParams &Params,
Callback<std::vector<ReferenceLocation>> Reply) {
+ llvm::errs() << "On reference call with doc: " << Params.textDocument.uri.file() << "\n";
+ llvm::errs() << "On reference call with position: " << Params.position << "\n";
Server->findReferences(Params.textDocument.uri.file(), Params.position,
Opts.ReferencesLimit, SupportsReferenceContainer,
[Reply = std::move(Reply),
@@ -1399,6 +1402,11 @@
});
}
+void ClangdLSPServer::onCodeLens(const CodeLensParams &Params,
+ Callback<std::vector<CodeLens>> Reply) {
+ Server->findCodeLens(Params.textDocument.uri.file(), std::move(Reply));
+}
+
void ClangdLSPServer::onGoToType(const TextDocumentPositionParams &Params,
Callback<std::vector<Location>> Reply) {
Server->findType(
@@ -1589,6 +1597,7 @@
Bind.method("textDocument/typeDefinition", this, &ClangdLSPServer::onGoToType);
Bind.method("textDocument/implementation", this, &ClangdLSPServer::onGoToImplementation);
Bind.method("textDocument/references", this, &ClangdLSPServer::onReference);
+ Bind.method("textDocument/codeLens", this, &ClangdLSPServer::onCodeLens);
Bind.method("textDocument/switchSourceHeader", this, &ClangdLSPServer::onSwitchSourceHeader);
Bind.method("textDocument/prepareRename", this, &ClangdLSPServer::onPrepareRename);
Bind.method("textDocument/rename", this, &ClangdLSPServer::onRename);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits