[mlir:PDLL] Add support for inlay hints

These allow for displaying additional inline information,
such as the types of variables, names operands/results,
constraint/rewrite arguments, etc. This requires a bump in the
vscode extension to a newer version, as inlay hints are a new LSP feature.

Differential Revision: https://reviews.llvm.org/D126033
This commit is contained in:
River Riddle 2022-05-17 17:56:17 -07:00
parent 6187178e83
commit 5919eab55c
11 changed files with 1727 additions and 497 deletions

View File

@ -219,6 +219,18 @@ necessarily provided by all IDE clients.
![IMG](/mlir-pdll-lsp-server/view_output.gif)
#### Inlay hints
The language server provides additional information inline with the source code.
Editors usually render this using read-only virtual text snippets interspersed
with code. Hints may be shown for:
* types of local variables
* names of operand and result groups
* constraint and rewrite arguments
![IMG](/mlir-pdll-lsp-server/inlay_hints.png)
## TableGen LSP Language Server : `tblgen-lsp-server`
MLIR provides an implementation of an LSP language server for `.td` text files

View File

@ -850,3 +850,45 @@ llvm::json::Value mlir::lsp::toJSON(const DocumentLink &value) {
{"target", value.target},
};
}
//===----------------------------------------------------------------------===//
// InlayHintsParams
//===----------------------------------------------------------------------===//
bool mlir::lsp::fromJSON(const llvm::json::Value &value,
InlayHintsParams &result, llvm::json::Path path) {
llvm::json::ObjectMapper o(value, path);
return o && o.map("textDocument", result.textDocument) &&
o.map("range", result.range);
}
//===----------------------------------------------------------------------===//
// InlayHint
//===----------------------------------------------------------------------===//
llvm::json::Value mlir::lsp::toJSON(const InlayHint &value) {
return llvm::json::Object{{"position", value.position},
{"kind", (int)value.kind},
{"label", value.label},
{"paddingLeft", value.paddingLeft},
{"paddingRight", value.paddingRight}};
}
bool mlir::lsp::operator==(const InlayHint &lhs, const InlayHint &rhs) {
return std::tie(lhs.position, lhs.kind, lhs.label) ==
std::tie(rhs.position, rhs.kind, rhs.label);
}
bool mlir::lsp::operator<(const InlayHint &lhs, const InlayHint &rhs) {
return std::tie(lhs.position, lhs.kind, lhs.label) <
std::tie(rhs.position, rhs.kind, rhs.label);
}
llvm::raw_ostream &mlir::lsp::operator<<(llvm::raw_ostream &os,
InlayHintKind value) {
switch (value) {
case InlayHintKind::Parameter:
return os << "parameter";
case InlayHintKind::Type:
return os << "type";
}
llvm_unreachable("Unknown InlayHintKind");
}

View File

@ -1000,6 +1000,86 @@ struct DocumentLink {
/// Add support for JSON serialization.
llvm::json::Value toJSON(const DocumentLink &value);
//===----------------------------------------------------------------------===//
// InlayHintsParams
//===----------------------------------------------------------------------===//
/// A parameter literal used in inlay hint requests.
struct InlayHintsParams {
/// The text document.
TextDocumentIdentifier textDocument;
/// The visible document range for which inlay hints should be computed.
Range range;
};
/// Add support for JSON serialization.
bool fromJSON(const llvm::json::Value &value, InlayHintsParams &result,
llvm::json::Path path);
//===----------------------------------------------------------------------===//
// InlayHintKind
//===----------------------------------------------------------------------===//
/// Inlay hint kinds.
enum class InlayHintKind {
/// An inlay hint that for a type annotation.
///
/// An example of a type hint is a hint in this position:
/// auto var ^ = expr;
/// which shows the deduced type of the variable.
Type = 1,
/// An inlay hint that is for a parameter.
///
/// An example of a parameter hint is a hint in this position:
/// func(^arg);
/// which shows the name of the corresponding parameter.
Parameter = 2,
};
//===----------------------------------------------------------------------===//
// InlayHint
//===----------------------------------------------------------------------===//
/// Inlay hint information.
struct InlayHint {
InlayHint(InlayHintKind kind, Position pos) : position(pos), kind(kind) {}
/// The position of this hint.
Position position;
/// The label of this hint. A human readable string or an array of
/// InlayHintLabelPart label parts.
///
/// *Note* that neither the string nor the label part can be empty.
std::string label;
/// The kind of this hint. Can be omitted in which case the client should fall
/// back to a reasonable default.
InlayHintKind kind;
/// Render padding before the hint.
///
/// Note: Padding should use the editor's background color, not the
/// background color of the hint itself. That means padding can be used
/// to visually align/separate an inlay hint.
bool paddingLeft = false;
/// Render padding after the hint.
///
/// Note: Padding should use the editor's background color, not the
/// background color of the hint itself. That means padding can be used
/// to visually align/separate an inlay hint.
bool paddingRight = false;
};
/// Add support for JSON serialization.
llvm::json::Value toJSON(const InlayHint &);
bool operator==(const InlayHint &lhs, const InlayHint &rhs);
bool operator<(const InlayHint &lhs, const InlayHint &rhs);
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, InlayHintKind value);
} // namespace lsp
} // namespace mlir

View File

@ -82,6 +82,12 @@ struct LSPServer {
void onSignatureHelp(const TextDocumentPositionParams &params,
Callback<SignatureHelp> reply);
//===--------------------------------------------------------------------===//
// Inlay Hints
void onInlayHint(const InlayHintsParams &params,
Callback<std::vector<InlayHint>> reply);
//===--------------------------------------------------------------------===//
// PDLL View Output
@ -140,6 +146,7 @@ void LSPServer::onInitialize(const InitializeParams &params,
}},
{"hoverProvider", true},
{"documentSymbolProvider", true},
{"inlayHintProvider", true},
};
llvm::json::Object result{
@ -248,6 +255,16 @@ void LSPServer::onSignatureHelp(const TextDocumentPositionParams &params,
reply(server.getSignatureHelp(params.textDocument.uri, params.position));
}
//===----------------------------------------------------------------------===//
// Inlay Hints
void LSPServer::onInlayHint(const InlayHintsParams &params,
Callback<std::vector<InlayHint>> reply) {
std::vector<InlayHint> hints;
server.getInlayHints(params.textDocument.uri, params.range, hints);
reply(std::move(hints));
}
//===----------------------------------------------------------------------===//
// PDLL ViewOutput
@ -305,6 +322,10 @@ LogicalResult mlir::lsp::runPdllLSPServer(PDLLServer &server,
messageHandler.method("textDocument/signatureHelp", &lspServer,
&LSPServer::onSignatureHelp);
// Inlay Hints
messageHandler.method("textDocument/inlayHint", &lspServer,
&LSPServer::onInlayHint);
// PDLL ViewOutput
messageHandler.method("pdll/viewOutput", &lspServer,
&LSPServer::onPDLLViewOutput);

View File

@ -62,6 +62,14 @@ static lsp::Location getLocationFromLoc(llvm::SourceMgr &mgr, SMRange range,
return lsp::Location(getURIFromLoc(mgr, range, uri), lsp::Range(mgr, range));
}
/// Returns true if the given range contains the given source location. Note
/// that this has different behavior than SMRange because it is inclusive of the
/// end location.
static bool contains(SMRange range, SMLoc loc) {
return range.Start.getPointer() <= loc.getPointer() &&
loc.getPointer() <= range.End.getPointer();
}
/// Convert the given MLIR diagnostic to the LSP form.
static Optional<lsp::Diagnostic>
getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr, const ast::Diagnostic &diag,
@ -358,6 +366,25 @@ struct PDLDocument {
lsp::SignatureHelp getSignatureHelp(const lsp::URIForFile &uri,
const lsp::Position &helpPos);
//===--------------------------------------------------------------------===//
// Inlay Hints
//===--------------------------------------------------------------------===//
void getInlayHints(const lsp::URIForFile &uri, const lsp::Range &range,
std::vector<lsp::InlayHint> &inlayHints);
void getInlayHintsFor(const ast::VariableDecl *decl,
const lsp::URIForFile &uri,
std::vector<lsp::InlayHint> &inlayHints);
void getInlayHintsFor(const ast::CallExpr *expr, const lsp::URIForFile &uri,
std::vector<lsp::InlayHint> &inlayHints);
void getInlayHintsFor(const ast::OperationExpr *expr,
const lsp::URIForFile &uri,
std::vector<lsp::InlayHint> &inlayHints);
/// Add a parameter hint for the given expression using `label`.
void addParameterHintFor(std::vector<lsp::InlayHint> &inlayHints,
const ast::Expr *expr, StringRef label);
//===--------------------------------------------------------------------===//
// PDLL ViewOutput
//===--------------------------------------------------------------------===//
@ -1169,6 +1196,153 @@ lsp::SignatureHelp PDLDocument::getSignatureHelp(const lsp::URIForFile &uri,
return signatureHelp;
}
//===----------------------------------------------------------------------===//
// PDLDocument: Inlay Hints
//===----------------------------------------------------------------------===//
/// Returns true if the given name should be added as a hint for `expr`.
static bool shouldAddHintFor(const ast::Expr *expr, StringRef name) {
if (name.empty())
return false;
// If the argument is a reference of the same name, don't add it as a hint.
if (auto *ref = dyn_cast<ast::DeclRefExpr>(expr)) {
const ast::Name *declName = ref->getDecl()->getName();
if (declName && declName->getName() == name)
return false;
}
return true;
}
void PDLDocument::getInlayHints(const lsp::URIForFile &uri,
const lsp::Range &range,
std::vector<lsp::InlayHint> &inlayHints) {
if (failed(astModule))
return;
SMRange rangeLoc = range.getAsSMRange(sourceMgr);
if (!rangeLoc.isValid())
return;
(*astModule)->walk([&](const ast::Node *node) {
SMRange loc = node->getLoc();
// Check that the location of this node is within the input range.
if (!contains(rangeLoc, loc.Start) && !contains(rangeLoc, loc.End))
return;
// Handle hints for various types of nodes.
llvm::TypeSwitch<const ast::Node *>(node)
.Case<ast::VariableDecl, ast::CallExpr, ast::OperationExpr>(
[&](const auto *node) {
this->getInlayHintsFor(node, uri, inlayHints);
});
});
}
void PDLDocument::getInlayHintsFor(const ast::VariableDecl *decl,
const lsp::URIForFile &uri,
std::vector<lsp::InlayHint> &inlayHints) {
// Check to see if the variable has a constraint list, if it does we don't
// provide initializer hints.
if (!decl->getConstraints().empty())
return;
// Check to see if the variable has an initializer.
if (const ast::Expr *expr = decl->getInitExpr()) {
// Don't add hints for operation expression initialized variables given that
// the type of the variable is easily inferred by the expression operation
// name.
if (isa<ast::OperationExpr>(expr))
return;
}
lsp::InlayHint hint(lsp::InlayHintKind::Type,
lsp::Position(sourceMgr, decl->getLoc().End));
{
llvm::raw_string_ostream labelOS(hint.label);
labelOS << ": " << decl->getType();
}
inlayHints.emplace_back(std::move(hint));
}
void PDLDocument::getInlayHintsFor(const ast::CallExpr *expr,
const lsp::URIForFile &uri,
std::vector<lsp::InlayHint> &inlayHints) {
// Try to extract the callable of this call.
const auto *callableRef = dyn_cast<ast::DeclRefExpr>(expr->getCallableExpr());
const auto *callable =
callableRef ? dyn_cast<ast::CallableDecl>(callableRef->getDecl())
: nullptr;
if (!callable)
return;
// Add hints for the arguments to the call.
for (const auto &it : llvm::zip(expr->getArguments(), callable->getInputs()))
addParameterHintFor(inlayHints, std::get<0>(it),
std::get<1>(it)->getName().getName());
}
void PDLDocument::getInlayHintsFor(const ast::OperationExpr *expr,
const lsp::URIForFile &uri,
std::vector<lsp::InlayHint> &inlayHints) {
// Check for ODS information.
ast::OperationType opType = expr->getType().dyn_cast<ast::OperationType>();
const auto *odsOp = opType ? opType.getODSOperation() : nullptr;
auto addOpHint = [&](const ast::Expr *valueExpr, StringRef label) {
// If the value expression used the same location as the operation, don't
// add a hint. This expression was materialized during parsing.
if (expr->getLoc().Start == valueExpr->getLoc().Start)
return;
addParameterHintFor(inlayHints, valueExpr, label);
};
// Functor used to process hints for the operands and results of the
// operation. They effectively have the same format, and thus can be processed
// using the same logic.
auto addOperandOrResultHints = [&](ArrayRef<ast::Expr *> values,
ArrayRef<ods::OperandOrResult> odsValues,
StringRef allValuesName) {
if (values.empty())
return;
// The values should either map to a single range, or be equivalent to the
// ODS values.
if (values.size() != odsValues.size()) {
// Handle the case of a single element that covers the full range.
if (values.size() == 1)
return addOpHint(values.front(), allValuesName);
return;
}
for (const auto &it : llvm::zip(values, odsValues))
addOpHint(std::get<0>(it), std::get<1>(it).getName());
};
// Add hints for the operands and results of the operation.
addOperandOrResultHints(expr->getOperands(),
odsOp ? odsOp->getOperands()
: ArrayRef<ods::OperandOrResult>(),
"operands");
addOperandOrResultHints(expr->getResultTypes(),
odsOp ? odsOp->getResults()
: ArrayRef<ods::OperandOrResult>(),
"results");
}
void PDLDocument::addParameterHintFor(std::vector<lsp::InlayHint> &inlayHints,
const ast::Expr *expr, StringRef label) {
if (!shouldAddHintFor(expr, label))
return;
lsp::InlayHint hint(lsp::InlayHintKind::Parameter,
lsp::Position(sourceMgr, expr->getLoc().Start));
hint.label = (label + ":").str();
hint.paddingRight = true;
inlayHints.emplace_back(std::move(hint));
}
//===----------------------------------------------------------------------===//
// PDLL ViewOutput
//===----------------------------------------------------------------------===//
@ -1271,9 +1445,14 @@ public:
lsp::Position completePos);
lsp::SignatureHelp getSignatureHelp(const lsp::URIForFile &uri,
lsp::Position helpPos);
void getInlayHints(const lsp::URIForFile &uri, lsp::Range range,
std::vector<lsp::InlayHint> &inlayHints);
lsp::PDLLViewOutputResult getPDLLViewOutput(lsp::PDLLViewOutputKind kind);
private:
using ChunkIterator = llvm::pointee_iterator<
std::vector<std::unique_ptr<PDLTextFileChunk>>::iterator>;
/// Initialize the text file from the given file contents.
void initialize(const lsp::URIForFile &uri, int64_t newVersion,
std::vector<lsp::Diagnostic> &diagnostics);
@ -1281,7 +1460,10 @@ private:
/// Find the PDL document that contains the given position, and update the
/// position to be anchored at the start of the found chunk instead of the
/// beginning of the file.
PDLTextFileChunk &getChunkFor(lsp::Position &pos);
ChunkIterator getChunkItFor(lsp::Position &pos);
PDLTextFileChunk &getChunkFor(lsp::Position &pos) {
return *getChunkItFor(pos);
}
/// The full string contents of the file.
std::string contents;
@ -1436,6 +1618,45 @@ lsp::SignatureHelp PDLTextFile::getSignatureHelp(const lsp::URIForFile &uri,
return getChunkFor(helpPos).document.getSignatureHelp(uri, helpPos);
}
void PDLTextFile::getInlayHints(const lsp::URIForFile &uri, lsp::Range range,
std::vector<lsp::InlayHint> &inlayHints) {
auto startIt = getChunkItFor(range.start);
auto endIt = getChunkItFor(range.end);
// Functor used to get the chunks for a given file, and fixup any locations
auto getHintsForChunk = [&](ChunkIterator chunkIt, lsp::Range range) {
size_t currentNumHints = inlayHints.size();
chunkIt->document.getInlayHints(uri, range, inlayHints);
// If this isn't the first chunk, update any positions to account for line
// number differences.
if (&*chunkIt != &*chunks.front()) {
for (auto &hint : llvm::drop_begin(inlayHints, currentNumHints))
chunkIt->adjustLocForChunkOffset(hint.position);
}
};
// Returns the number of lines held by a given chunk.
auto getNumLines = [](ChunkIterator chunkIt) {
return (chunkIt + 1)->lineOffset - chunkIt->lineOffset;
};
// Check if the range is fully within a single chunk.
if (startIt == endIt)
return getHintsForChunk(startIt, range);
// Otherwise, the range is split between multiple chunks. The first chunk
// has the correct range start, but covers the total document.
getHintsForChunk(startIt, lsp::Range(range.start, getNumLines(startIt)));
// Every chunk in between uses the full document.
for (++startIt; startIt != endIt; ++startIt)
getHintsForChunk(startIt, lsp::Range(0, getNumLines(startIt)));
// The range for the last chunk starts at the beginning of the document, up
// through the end of the input range.
getHintsForChunk(startIt, lsp::Range(0, range.end));
}
lsp::PDLLViewOutputResult
PDLTextFile::getPDLLViewOutput(lsp::PDLLViewOutputKind kind) {
lsp::PDLLViewOutputResult result;
@ -1490,9 +1711,9 @@ void PDLTextFile::initialize(const lsp::URIForFile &uri, int64_t newVersion,
totalNumLines = lineOffset;
}
PDLTextFileChunk &PDLTextFile::getChunkFor(lsp::Position &pos) {
PDLTextFile::ChunkIterator PDLTextFile::getChunkItFor(lsp::Position &pos) {
if (chunks.size() == 1)
return *chunks.front();
return chunks.begin();
// Search for the first chunk with a greater line offset, the previous chunk
// is the one that contains `pos`.
@ -1500,9 +1721,9 @@ PDLTextFileChunk &PDLTextFile::getChunkFor(lsp::Position &pos) {
chunks, pos, [](const lsp::Position &pos, const auto &chunk) {
return static_cast<uint64_t>(pos.line) < chunk->lineOffset;
});
PDLTextFileChunk &chunk = it == chunks.end() ? *chunks.back() : **(--it);
pos.line -= chunk.lineOffset;
return chunk;
ChunkIterator chunkIt(it == chunks.end() ? (chunks.end() - 1) : --it);
pos.line -= chunkIt->lineOffset;
return chunkIt;
}
//===----------------------------------------------------------------------===//
@ -1623,6 +1844,19 @@ lsp::SignatureHelp lsp::PDLLServer::getSignatureHelp(const URIForFile &uri,
return SignatureHelp();
}
void lsp::PDLLServer::getInlayHints(const URIForFile &uri, const Range &range,
std::vector<InlayHint> &inlayHints) {
auto fileIt = impl->files.find(uri.file());
if (fileIt == impl->files.end())
return;
fileIt->second->getInlayHints(uri, range, inlayHints);
// Drop any duplicated hints that may have cropped up.
llvm::sort(inlayHints);
inlayHints.erase(std::unique(inlayHints.begin(), inlayHints.end()),
inlayHints.end());
}
Optional<lsp::PDLLViewOutputResult>
lsp::PDLLServer::getPDLLViewOutput(const URIForFile &uri,
PDLLViewOutputKind kind) {

View File

@ -24,8 +24,10 @@ struct CompletionList;
struct DocumentLink;
struct DocumentSymbol;
struct Hover;
struct InlayHint;
struct Location;
struct Position;
struct Range;
struct SignatureHelp;
struct TextDocumentContentChangeEvent;
class URIForFile;
@ -95,6 +97,10 @@ public:
SignatureHelp getSignatureHelp(const URIForFile &uri,
const Position &helpPos);
/// Get the inlay hints for the range within the given file.
void getInlayHints(const URIForFile &uri, const Range &range,
std::vector<InlayHint> &inlayHints);
/// Get the output of the given PDLL file, or None if there is no valid
/// output.
Optional<PDLLViewOutputResult> getPDLLViewOutput(const URIForFile &uri,

View File

@ -18,6 +18,7 @@
// CHECK-NEXT: },
// CHECK-NEXT: "documentSymbolProvider": true,
// CHECK-NEXT: "hoverProvider": true,
// CHECK-NEXT: "inlayHintProvider": true,
// CHECK-NEXT: "referencesProvider": true,
// CHECK-NEXT: "signatureHelpProvider": {
// CHECK-NEXT: "triggerCharacters": [

View File

@ -0,0 +1,107 @@
// RUN: mlir-pdll-lsp-server -pdll-extra-dir %S -pdll-extra-dir %S/../../include -lit-test < %s | FileCheck -strict-whitespace %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":"#include \"include/included.td\"\nConstraint Cst(attr: Attr);\nPattern {\n op<test.multi>(_: Value, _: Value);\n op<test.multi>(_: ValueRange) -> (_: Type, _: Type);\n let op = op<test.multi>;\n let value = op.0;\n Cst(_: Attr);\n erase op;\n}\n"
}}}
// -----
{"jsonrpc":"2.0","id":2,"method":"textDocument/inlayHint","params":{
"textDocument":{"uri":"test:///foo.pdll"},
"range": {
"start": {"line":3,"character":0},
"end": {"line":5,"character":0}
}
}}
// CHECK: "id": 2,
// CHECK-NEXT: "jsonrpc": "2.0",
// CHECK-NEXT: "result": [
// CHECK-NEXT: {
// CHECK-NEXT: "kind": 2,
// CHECK-NEXT: "label": "operand:",
// CHECK-NEXT: "paddingLeft": false,
// CHECK-NEXT: "paddingRight": true,
// CHECK-NEXT: "position": {
// CHECK-NEXT: "character": 17,
// CHECK-NEXT: "line": 3
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": 2,
// CHECK-NEXT: "label": "operand2:",
// CHECK-NEXT: "paddingLeft": false,
// CHECK-NEXT: "paddingRight": true,
// CHECK-NEXT: "position": {
// CHECK-NEXT: "character": 27,
// CHECK-NEXT: "line": 3
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": 2,
// CHECK-NEXT: "label": "operands:",
// CHECK-NEXT: "paddingLeft": false,
// CHECK-NEXT: "paddingRight": true,
// CHECK-NEXT: "position": {
// CHECK-NEXT: "character": 17,
// CHECK-NEXT: "line": 4
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": 2,
// CHECK-NEXT: "label": "result:",
// CHECK-NEXT: "paddingLeft": false,
// CHECK-NEXT: "paddingRight": true,
// CHECK-NEXT: "position": {
// CHECK-NEXT: "character": 36,
// CHECK-NEXT: "line": 4
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": 2,
// CHECK-NEXT: "label": "result2:",
// CHECK-NEXT: "paddingLeft": false,
// CHECK-NEXT: "paddingRight": true,
// CHECK-NEXT: "position": {
// CHECK-NEXT: "character": 45,
// CHECK-NEXT: "line": 4
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// -----
{"jsonrpc":"2.0","id":3,"method":"textDocument/inlayHint","params":{
"textDocument":{"uri":"test:///foo.pdll"},
"range": {
"start": {"line":5,"character":0},
"end": {"line":8,"character":0}
}
}}
// CHECK: "id": 3,
// CHECK-NEXT: "jsonrpc": "2.0",
// CHECK-NEXT: "result": [
// CHECK-NEXT: {
// CHECK-NEXT: "kind": 1,
// CHECK-NEXT: "label": ": Value",
// CHECK-NEXT: "paddingLeft": false,
// CHECK-NEXT: "paddingRight": false,
// CHECK-NEXT: "position": {
// CHECK-NEXT: "character": 11,
// CHECK-NEXT: "line": 6
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": 2,
// CHECK-NEXT: "label": "attr:",
// CHECK-NEXT: "paddingLeft": false,
// CHECK-NEXT: "paddingRight": true,
// CHECK-NEXT: "position": {
// CHECK-NEXT: "character": 6,
// CHECK-NEXT: "line": 7
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// -----
{"jsonrpc":"2.0","id":4,"method":"shutdown"}
// -----
{"jsonrpc":"2.0","method":"exit"}

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
"homepage": "https://mlir.llvm.org/",
"icon": "icon.png",
"engines": {
"vscode": "^1.52.0"
"vscode": "^1.67.0"
},
"categories": [
"Programming Languages"
@ -36,17 +36,15 @@
},
"dependencies": {
"chokidar": "3.5.2",
"vscode-languageclient": "^5.2.1",
"vscode-languageserver-types": "3.16.0"
"vscode-languageclient": "^8.0.1"
},
"devDependencies": {
"@types/mocha": "^5.2.0",
"@types/node": "^8.0.0",
"@types/vscode": "1.52.*",
"clang-format": "1.4.0",
"tslint": "^5.16.0",
"typescript": "^3.5.1",
"vsce": "^1.75.0",
"@types/mocha": "^7.0.2",
"@types/node": "^14.17.0",
"@types/vscode": "~1.67.0",
"clang-format": "^1.8.0",
"typescript": "^4.6.4",
"vsce": "^2.7.0",
"vscode-test": "^1.3.0"
},
"repository": {

View File

@ -1,7 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';
import * as vscodelc from 'vscode-languageclient';
import * as vscodelc from 'vscode-languageclient/node';
import * as config from './config';
import * as configWatcher from './configWatcher';
@ -11,7 +11,7 @@ import * as configWatcher from './configWatcher';
*/
class WorkspaceFolderContext implements vscode.Disposable {
dispose() {
this.clients.forEach(client => client.stop());
this.clients.forEach(async client => await client.stop());
this.clients.clear();
}
@ -229,16 +229,8 @@ export class MLIRContext implements vscode.Disposable {
// Configure the server options.
const serverOptions: vscodelc.ServerOptions = {
run : {
command : serverPath,
transport : vscodelc.TransportKind.stdio,
args : additionalServerArgs
},
debug : {
command : serverPath,
transport : vscodelc.TransportKind.stdio,
args : additionalServerArgs
}
command : serverPath,
args : additionalServerArgs
};
// Configure file patterns relative to the workspace folder.
@ -279,7 +271,10 @@ export class MLIRContext implements vscode.Disposable {
},
outputChannel : outputChannel,
workspaceFolder : workspaceFolder,
middleware : middleware
middleware : middleware,
// Don't switch to output window when the server returns output.
revealOutputChannelOn : vscodelc.RevealOutputChannelOn.Never,
};
// Create the language client and start the client.