forked from OSchip/llvm-project
[mlir][PDLL] Add hover support to the PDLL language server
This adds support for providing information when hovering over operation names, variables, patters, constraints, and rewrites. Differential Revision: https://reviews.llvm.org/D121542
This commit is contained in:
parent
52b34df9d6
commit
41ae211458
|
@ -52,6 +52,12 @@ struct LSPServer {
|
||||||
void onReference(const ReferenceParams ¶ms,
|
void onReference(const ReferenceParams ¶ms,
|
||||||
Callback<std::vector<Location>> reply);
|
Callback<std::vector<Location>> reply);
|
||||||
|
|
||||||
|
//===--------------------------------------------------------------------===//
|
||||||
|
// Hover
|
||||||
|
|
||||||
|
void onHover(const TextDocumentPositionParams ¶ms,
|
||||||
|
Callback<Optional<Hover>> reply);
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Fields
|
// Fields
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -84,6 +90,7 @@ void LSPServer::onInitialize(const InitializeParams ¶ms,
|
||||||
}},
|
}},
|
||||||
{"definitionProvider", true},
|
{"definitionProvider", true},
|
||||||
{"referencesProvider", true},
|
{"referencesProvider", true},
|
||||||
|
{"hoverProvider", true},
|
||||||
};
|
};
|
||||||
|
|
||||||
llvm::json::Object result{
|
llvm::json::Object result{
|
||||||
|
@ -154,6 +161,14 @@ void LSPServer::onReference(const ReferenceParams ¶ms,
|
||||||
reply(std::move(locations));
|
reply(std::move(locations));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Hover
|
||||||
|
|
||||||
|
void LSPServer::onHover(const TextDocumentPositionParams ¶ms,
|
||||||
|
Callback<Optional<Hover>> reply) {
|
||||||
|
reply(server.findHover(params.textDocument.uri, params.position));
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Entry Point
|
// Entry Point
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -183,6 +198,9 @@ LogicalResult mlir::lsp::runPdllLSPServer(PDLLServer &server,
|
||||||
messageHandler.method("textDocument/references", &lspServer,
|
messageHandler.method("textDocument/references", &lspServer,
|
||||||
&LSPServer::onReference);
|
&LSPServer::onReference);
|
||||||
|
|
||||||
|
// Hover
|
||||||
|
messageHandler.method("textDocument/hover", &lspServer, &LSPServer::onHover);
|
||||||
|
|
||||||
// Diagnostics
|
// Diagnostics
|
||||||
lspServer.publishDiagnostics =
|
lspServer.publishDiagnostics =
|
||||||
messageHandler.outgoingNotification<PublishDiagnosticsParams>(
|
messageHandler.outgoingNotification<PublishDiagnosticsParams>(
|
||||||
|
|
|
@ -244,6 +244,27 @@ struct PDLDocument {
|
||||||
void findReferencesOf(const lsp::URIForFile &uri, const lsp::Position &pos,
|
void findReferencesOf(const lsp::URIForFile &uri, const lsp::Position &pos,
|
||||||
std::vector<lsp::Location> &references);
|
std::vector<lsp::Location> &references);
|
||||||
|
|
||||||
|
//===--------------------------------------------------------------------===//
|
||||||
|
// Hover
|
||||||
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
Optional<lsp::Hover> findHover(const lsp::URIForFile &uri,
|
||||||
|
const lsp::Position &hoverPos);
|
||||||
|
Optional<lsp::Hover> findHover(const ast::Decl *decl,
|
||||||
|
const SMRange &hoverRange);
|
||||||
|
lsp::Hover buildHoverForOpName(const ods::Operation *op,
|
||||||
|
const SMRange &hoverRange);
|
||||||
|
lsp::Hover buildHoverForVariable(const ast::VariableDecl *varDecl,
|
||||||
|
const SMRange &hoverRange);
|
||||||
|
lsp::Hover buildHoverForPattern(const ast::PatternDecl *patternDecl,
|
||||||
|
const SMRange &hoverRange);
|
||||||
|
lsp::Hover buildHoverForCoreConstraint(const ast::CoreConstraintDecl *decl,
|
||||||
|
const SMRange &hoverRange);
|
||||||
|
template <typename T>
|
||||||
|
lsp::Hover buildHoverForUserConstraintOrRewrite(StringRef typeName,
|
||||||
|
const T *decl,
|
||||||
|
const SMRange &hoverRange);
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Fields
|
// Fields
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -320,6 +341,157 @@ void PDLDocument::findReferencesOf(const lsp::URIForFile &uri,
|
||||||
references.push_back(getLocationFromLoc(sourceMgr, refLoc, uri));
|
references.push_back(getLocationFromLoc(sourceMgr, refLoc, uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// PDLDocument: Hover
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
Optional<lsp::Hover> PDLDocument::findHover(const lsp::URIForFile &uri,
|
||||||
|
const lsp::Position &hoverPos) {
|
||||||
|
SMLoc posLoc = hoverPos.getAsSMLoc(sourceMgr);
|
||||||
|
SMRange hoverRange;
|
||||||
|
const PDLIndexSymbol *symbol = index.lookup(posLoc, &hoverRange);
|
||||||
|
if (!symbol)
|
||||||
|
return llvm::None;
|
||||||
|
|
||||||
|
// Add hover for operation names.
|
||||||
|
if (const auto *op = symbol->definition.dyn_cast<const ods::Operation *>())
|
||||||
|
return buildHoverForOpName(op, hoverRange);
|
||||||
|
const auto *decl = symbol->definition.get<const ast::Decl *>();
|
||||||
|
return findHover(decl, hoverRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<lsp::Hover> PDLDocument::findHover(const ast::Decl *decl,
|
||||||
|
const SMRange &hoverRange) {
|
||||||
|
// Add hover for variables.
|
||||||
|
if (const auto *varDecl = dyn_cast<ast::VariableDecl>(decl))
|
||||||
|
return buildHoverForVariable(varDecl, hoverRange);
|
||||||
|
|
||||||
|
// Add hover for patterns.
|
||||||
|
if (const auto *patternDecl = dyn_cast<ast::PatternDecl>(decl))
|
||||||
|
return buildHoverForPattern(patternDecl, hoverRange);
|
||||||
|
|
||||||
|
// Add hover for core constraints.
|
||||||
|
if (const auto *cst = dyn_cast<ast::CoreConstraintDecl>(decl))
|
||||||
|
return buildHoverForCoreConstraint(cst, hoverRange);
|
||||||
|
|
||||||
|
// Add hover for user constraints.
|
||||||
|
if (const auto *cst = dyn_cast<ast::UserConstraintDecl>(decl))
|
||||||
|
return buildHoverForUserConstraintOrRewrite("Constraint", cst, hoverRange);
|
||||||
|
|
||||||
|
// Add hover for user rewrites.
|
||||||
|
if (const auto *rewrite = dyn_cast<ast::UserRewriteDecl>(decl))
|
||||||
|
return buildHoverForUserConstraintOrRewrite("Rewrite", rewrite, hoverRange);
|
||||||
|
|
||||||
|
return llvm::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
lsp::Hover PDLDocument::buildHoverForOpName(const ods::Operation *op,
|
||||||
|
const SMRange &hoverRange) {
|
||||||
|
lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
|
||||||
|
{
|
||||||
|
llvm::raw_string_ostream hoverOS(hover.contents.value);
|
||||||
|
hoverOS << "**OpName**: `" << op->getName() << "`\n***\n"
|
||||||
|
<< op->getSummary() << "\n***\n"
|
||||||
|
<< op->getDescription();
|
||||||
|
}
|
||||||
|
return hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
lsp::Hover PDLDocument::buildHoverForVariable(const ast::VariableDecl *varDecl,
|
||||||
|
const SMRange &hoverRange) {
|
||||||
|
lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
|
||||||
|
{
|
||||||
|
llvm::raw_string_ostream hoverOS(hover.contents.value);
|
||||||
|
hoverOS << "**Variable**: `" << varDecl->getName().getName() << "`\n***\n"
|
||||||
|
<< "Type: `" << varDecl->getType() << "`\n";
|
||||||
|
}
|
||||||
|
return hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
lsp::Hover
|
||||||
|
PDLDocument::buildHoverForPattern(const ast::PatternDecl *patternDecl,
|
||||||
|
const SMRange &hoverRange) {
|
||||||
|
lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
|
||||||
|
{
|
||||||
|
llvm::raw_string_ostream hoverOS(hover.contents.value);
|
||||||
|
hoverOS << "**Pattern**";
|
||||||
|
if (const ast::Name *name = patternDecl->getName())
|
||||||
|
hoverOS << ": `" << name->getName() << "`";
|
||||||
|
hoverOS << "\n***\n";
|
||||||
|
if (Optional<uint16_t> benefit = patternDecl->getBenefit())
|
||||||
|
hoverOS << "Benefit: " << *benefit << "\n";
|
||||||
|
if (patternDecl->hasBoundedRewriteRecursion())
|
||||||
|
hoverOS << "HasBoundedRewriteRecursion\n";
|
||||||
|
hoverOS << "RootOp: `"
|
||||||
|
<< patternDecl->getRootRewriteStmt()->getRootOpExpr()->getType()
|
||||||
|
<< "`\n";
|
||||||
|
}
|
||||||
|
return hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
lsp::Hover
|
||||||
|
PDLDocument::buildHoverForCoreConstraint(const ast::CoreConstraintDecl *decl,
|
||||||
|
const SMRange &hoverRange) {
|
||||||
|
lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
|
||||||
|
{
|
||||||
|
llvm::raw_string_ostream hoverOS(hover.contents.value);
|
||||||
|
hoverOS << "**Constraint**: `";
|
||||||
|
TypeSwitch<const ast::Decl *>(decl)
|
||||||
|
.Case([&](const ast::AttrConstraintDecl *) { hoverOS << "Attr"; })
|
||||||
|
.Case([&](const ast::OpConstraintDecl *opCst) {
|
||||||
|
hoverOS << "Op";
|
||||||
|
if (Optional<StringRef> name = opCst->getName())
|
||||||
|
hoverOS << "<" << name << ">";
|
||||||
|
})
|
||||||
|
.Case([&](const ast::TypeConstraintDecl *) { hoverOS << "Type"; })
|
||||||
|
.Case([&](const ast::TypeRangeConstraintDecl *) {
|
||||||
|
hoverOS << "TypeRange";
|
||||||
|
})
|
||||||
|
.Case([&](const ast::ValueConstraintDecl *) { hoverOS << "Value"; })
|
||||||
|
.Case([&](const ast::ValueRangeConstraintDecl *) {
|
||||||
|
hoverOS << "ValueRange";
|
||||||
|
});
|
||||||
|
hoverOS << "`\n";
|
||||||
|
}
|
||||||
|
return hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
lsp::Hover PDLDocument::buildHoverForUserConstraintOrRewrite(
|
||||||
|
StringRef typeName, const T *decl, const SMRange &hoverRange) {
|
||||||
|
lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
|
||||||
|
{
|
||||||
|
llvm::raw_string_ostream hoverOS(hover.contents.value);
|
||||||
|
hoverOS << "**" << typeName << "**: `" << decl->getName().getName()
|
||||||
|
<< "`\n***\n";
|
||||||
|
ArrayRef<ast::VariableDecl *> inputs = decl->getInputs();
|
||||||
|
if (!inputs.empty()) {
|
||||||
|
hoverOS << "Parameters:\n";
|
||||||
|
for (const ast::VariableDecl *input : inputs)
|
||||||
|
hoverOS << "* " << input->getName().getName() << ": `"
|
||||||
|
<< input->getType() << "`\n";
|
||||||
|
hoverOS << "***\n";
|
||||||
|
}
|
||||||
|
ast::Type resultType = decl->getResultType();
|
||||||
|
if (auto resultTupleTy = resultType.dyn_cast<ast::TupleType>()) {
|
||||||
|
if (resultTupleTy.empty())
|
||||||
|
return hover;
|
||||||
|
|
||||||
|
hoverOS << "Results:\n";
|
||||||
|
for (auto it : llvm::zip(resultTupleTy.getElementNames(),
|
||||||
|
resultTupleTy.getElementTypes())) {
|
||||||
|
StringRef name = std::get<0>(it);
|
||||||
|
hoverOS << "* " << (name.empty() ? "" : (name + ": ")) << "`"
|
||||||
|
<< std::get<1>(it) << "`\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hoverOS << "Results:\n* `" << resultType << "`\n";
|
||||||
|
}
|
||||||
|
hoverOS << "***\n";
|
||||||
|
}
|
||||||
|
return hover;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// PDLTextFileChunk
|
// PDLTextFileChunk
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -371,6 +543,8 @@ public:
|
||||||
std::vector<lsp::Location> &locations);
|
std::vector<lsp::Location> &locations);
|
||||||
void findReferencesOf(const lsp::URIForFile &uri, lsp::Position pos,
|
void findReferencesOf(const lsp::URIForFile &uri, lsp::Position pos,
|
||||||
std::vector<lsp::Location> &references);
|
std::vector<lsp::Location> &references);
|
||||||
|
Optional<lsp::Hover> findHover(const lsp::URIForFile &uri,
|
||||||
|
lsp::Position hoverPos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Find the PDL document that contains the given position, and update the
|
/// Find the PDL document that contains the given position, and update the
|
||||||
|
@ -458,6 +632,17 @@ void PDLTextFile::findReferencesOf(const lsp::URIForFile &uri,
|
||||||
chunk.adjustLocForChunkOffset(loc.range);
|
chunk.adjustLocForChunkOffset(loc.range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<lsp::Hover> PDLTextFile::findHover(const lsp::URIForFile &uri,
|
||||||
|
lsp::Position hoverPos) {
|
||||||
|
PDLTextFileChunk &chunk = getChunkFor(hoverPos);
|
||||||
|
Optional<lsp::Hover> hoverInfo = chunk.document.findHover(uri, hoverPos);
|
||||||
|
|
||||||
|
// Adjust any locations within this file for the offset of this chunk.
|
||||||
|
if (chunk.lineOffset != 0 && hoverInfo && hoverInfo->range)
|
||||||
|
chunk.adjustLocForChunkOffset(*hoverInfo->range);
|
||||||
|
return hoverInfo;
|
||||||
|
}
|
||||||
|
|
||||||
PDLTextFileChunk &PDLTextFile::getChunkFor(lsp::Position &pos) {
|
PDLTextFileChunk &PDLTextFile::getChunkFor(lsp::Position &pos) {
|
||||||
if (chunks.size() == 1)
|
if (chunks.size() == 1)
|
||||||
return *chunks.front();
|
return *chunks.front();
|
||||||
|
@ -521,3 +706,11 @@ void lsp::PDLLServer::findReferencesOf(const URIForFile &uri,
|
||||||
if (fileIt != impl->files.end())
|
if (fileIt != impl->files.end())
|
||||||
fileIt->second->findReferencesOf(uri, pos, references);
|
fileIt->second->findReferencesOf(uri, pos, references);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<lsp::Hover> lsp::PDLLServer::findHover(const URIForFile &uri,
|
||||||
|
const Position &hoverPos) {
|
||||||
|
auto fileIt = impl->files.find(uri.file());
|
||||||
|
if (fileIt != impl->files.end())
|
||||||
|
return fileIt->second->findHover(uri, hoverPos);
|
||||||
|
return llvm::None;
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
namespace mlir {
|
namespace mlir {
|
||||||
namespace lsp {
|
namespace lsp {
|
||||||
struct Diagnostic;
|
struct Diagnostic;
|
||||||
|
struct Hover;
|
||||||
struct Location;
|
struct Location;
|
||||||
struct Position;
|
struct Position;
|
||||||
class URIForFile;
|
class URIForFile;
|
||||||
|
@ -47,6 +48,10 @@ public:
|
||||||
void findReferencesOf(const URIForFile &uri, const Position &pos,
|
void findReferencesOf(const URIForFile &uri, const Position &pos,
|
||||||
std::vector<Location> &references);
|
std::vector<Location> &references);
|
||||||
|
|
||||||
|
/// Find a hover description for the given hover position, or None if one
|
||||||
|
/// couldn't be found.
|
||||||
|
Optional<Hover> findHover(const URIForFile &uri, const Position &hoverPos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
// RUN: mlir-pdll-lsp-server -lit-test < %s | FileCheck %s
|
||||||
|
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"pdll","capabilities":{},"trace":"off"}}
|
||||||
|
// -----
|
||||||
|
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{
|
||||||
|
"uri":"test:///foo.pdll",
|
||||||
|
"languageId":"pdll",
|
||||||
|
"version":1,
|
||||||
|
"text":"Constraint FooCst();\nRewrite FooRewrite(op: Op) -> Op;\nPattern Foo {\nlet root: Op;\nerase root;\n}"
|
||||||
|
}}}
|
||||||
|
// -----
|
||||||
|
// Hover on a variable.
|
||||||
|
{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{
|
||||||
|
"textDocument":{"uri":"test:///foo.pdll"},
|
||||||
|
"position":{"line":3,"character":6}
|
||||||
|
}}
|
||||||
|
// CHECK: "id": 1,
|
||||||
|
// CHECK-NEXT: "jsonrpc": "2.0",
|
||||||
|
// CHECK-NEXT: "result": {
|
||||||
|
// CHECK-NEXT: "contents": {
|
||||||
|
// CHECK-NEXT: "kind": "markdown",
|
||||||
|
// CHECK-NEXT: "value": "**Variable**: `root`\n***\nType: `Op`\n"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "character": 8,
|
||||||
|
// CHECK-NEXT: "line": 3
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "start": {
|
||||||
|
// CHECK-NEXT: "character": 4,
|
||||||
|
// CHECK-NEXT: "line": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// -----
|
||||||
|
// Hover on a pattern.
|
||||||
|
{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{
|
||||||
|
"textDocument":{"uri":"test:///foo.pdll"},
|
||||||
|
"position":{"line":2,"character":9}
|
||||||
|
}}
|
||||||
|
// CHECK: "id": 1,
|
||||||
|
// CHECK-NEXT: "jsonrpc": "2.0",
|
||||||
|
// CHECK-NEXT: "result": {
|
||||||
|
// CHECK-NEXT: "contents": {
|
||||||
|
// CHECK-NEXT: "kind": "markdown",
|
||||||
|
// CHECK-NEXT: "value": "**Pattern**: `Foo`\n***\nRootOp: `Op`\n"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "character": 11,
|
||||||
|
// CHECK-NEXT: "line": 2
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "start": {
|
||||||
|
// CHECK-NEXT: "character": 8,
|
||||||
|
// CHECK-NEXT: "line": 2
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// -----
|
||||||
|
// Hover on a core constraint.
|
||||||
|
{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{
|
||||||
|
"textDocument":{"uri":"test:///foo.pdll"},
|
||||||
|
"position":{"line":3,"character":11}
|
||||||
|
}}
|
||||||
|
// CHECK: "id": 1,
|
||||||
|
// CHECK-NEXT: "jsonrpc": "2.0",
|
||||||
|
// CHECK-NEXT: "result": {
|
||||||
|
// CHECK-NEXT: "contents": {
|
||||||
|
// CHECK-NEXT: "kind": "markdown",
|
||||||
|
// CHECK-NEXT: "value": "**Constraint**: `Op`\n"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "character": 12,
|
||||||
|
// CHECK-NEXT: "line": 3
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "start": {
|
||||||
|
// CHECK-NEXT: "character": 10,
|
||||||
|
// CHECK-NEXT: "line": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// -----
|
||||||
|
// Hover on a user constraint.
|
||||||
|
{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{
|
||||||
|
"textDocument":{"uri":"test:///foo.pdll"},
|
||||||
|
"position":{"line":0,"character":14}
|
||||||
|
}}
|
||||||
|
// CHECK: "id": 1,
|
||||||
|
// CHECK-NEXT: "jsonrpc": "2.0",
|
||||||
|
// CHECK-NEXT: "result": {
|
||||||
|
// CHECK-NEXT: "contents": {
|
||||||
|
// CHECK-NEXT: "kind": "markdown",
|
||||||
|
// CHECK-NEXT: "value": "**Constraint**: `FooCst`\n***\n"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "character": 17,
|
||||||
|
// CHECK-NEXT: "line": 0
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "start": {
|
||||||
|
// CHECK-NEXT: "character": 11,
|
||||||
|
// CHECK-NEXT: "line": 0
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// -----
|
||||||
|
// Hover on a user rewrite.
|
||||||
|
{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{
|
||||||
|
"textDocument":{"uri":"test:///foo.pdll"},
|
||||||
|
"position":{"line":1,"character":11}
|
||||||
|
}}
|
||||||
|
// CHECK: "id": 1,
|
||||||
|
// CHECK-NEXT: "jsonrpc": "2.0",
|
||||||
|
// CHECK-NEXT: "result": {
|
||||||
|
// CHECK-NEXT: "contents": {
|
||||||
|
// CHECK-NEXT: "kind": "markdown",
|
||||||
|
// CHECK-NEXT: "value": "**Rewrite**: `FooRewrite`\n***\nParameters:\n* op: `Op`\n***\nResults:\n* `Op`\n***\n"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "character": 18,
|
||||||
|
// CHECK-NEXT: "line": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "start": {
|
||||||
|
// CHECK-NEXT: "character": 8,
|
||||||
|
// CHECK-NEXT: "line": 1
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// -----
|
||||||
|
{"jsonrpc":"2.0","id":7,"method":"shutdown"}
|
||||||
|
// -----
|
||||||
|
{"jsonrpc":"2.0","method":"exit"}
|
|
@ -6,6 +6,7 @@
|
||||||
// CHECK-NEXT: "result": {
|
// CHECK-NEXT: "result": {
|
||||||
// CHECK-NEXT: "capabilities": {
|
// CHECK-NEXT: "capabilities": {
|
||||||
// CHECK-NEXT: "definitionProvider": true,
|
// CHECK-NEXT: "definitionProvider": true,
|
||||||
|
// CHECK-NEXT: "hoverProvider": true,
|
||||||
// CHECK-NEXT: "referencesProvider": true,
|
// CHECK-NEXT: "referencesProvider": true,
|
||||||
// CHECK-NEXT: "textDocumentSync": {
|
// CHECK-NEXT: "textDocumentSync": {
|
||||||
// CHECK-NEXT: "change": 1,
|
// CHECK-NEXT: "change": 1,
|
||||||
|
|
Loading…
Reference in New Issue