21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/Support/Base64.h"
23 #include "llvm/Support/SourceMgr.h"
49 position.
line = loc.getLine() - 1;
50 position.
character = loc.getColumn() ? loc.getColumn() - 1 : 0;
58 static std::optional<lsp::Location>
61 std::optional<lsp::Location> location;
63 FileLineColLoc fileLoc = dyn_cast<FileLineColLoc>(nestedLoc);
67 std::optional<lsp::Location> sourceLoc =
69 if (sourceLoc && (!uri || sourceLoc->uri == *uri)) {
70 location = *sourceLoc;
71 SMLoc loc = sourceMgr.FindLocForLineAndColumn(
72 sourceMgr.getMainFileID(), fileLoc.getLine(), fileLoc.getColumn());
76 location->range.end.character += 1;
78 auto lineCol = sourceMgr.getLineAndColumn(range->End);
79 location->range.end.character =
80 std::max(fileLoc.getColumn() + 1, lineCol.second - 1);
92 std::vector<lsp::Location> &locations,
96 FileLineColLoc fileLoc = dyn_cast<FileLineColLoc>(nestedLoc);
97 if (!fileLoc || !visitedLocs.insert(nestedLoc))
100 std::optional<lsp::Location> sourceLoc =
102 if (sourceLoc && sourceLoc->uri != uri)
103 locations.push_back(*sourceLoc);
112 return range.Start.getPointer() <= loc.getPointer() &&
113 loc.getPointer() <= range.End.getPointer();
120 SMRange *overlappedRange =
nullptr) {
124 *overlappedRange = def.
loc;
129 const auto *useIt = llvm::find_if(
130 def.
uses, [&](
const SMRange &range) { return contains(range, loc); });
131 if (useIt != def.
uses.end()) {
133 *overlappedRange = *useIt;
143 auto isIdentifierChar = [](
char c) {
144 return isalnum(c) || c ==
'%' || c ==
'$' || c ==
'.' || c ==
'_' ||
147 const char *curPtr = loc.getPointer();
148 while (isIdentifierChar(*curPtr))
157 const char *numberStart = ++curPtr;
158 while (llvm::isDigit(*curPtr))
160 StringRef numberStr(numberStart, curPtr - numberStart);
161 unsigned resultNumber = 0;
162 return numberStr.consumeInteger(10, resultNumber) ? std::optional<unsigned>()
169 if (!range.isValid())
171 const char *startPtr = range.Start.getPointer();
172 return StringRef(startPtr, range.End.getPointer() - startPtr);
177 return std::distance(block->
getParent()->
begin(), block->getIterator());
185 if (text && text->starts_with(
"^")) {
212 StringRef uriScheme = uri.
scheme();
213 std::optional<lsp::Location> lspLocation =
216 lspDiag.
range = lspLocation->range;
219 switch (
diag.getSeverity()) {
221 llvm_unreachable(
"expected notes to be handled separately");
235 std::vector<lsp::DiagnosticRelatedInformation> relatedDiags;
238 if (std::optional<lsp::Location> loc =
243 relatedDiags.emplace_back(noteLoc, note.str());
245 if (!relatedDiags.empty())
258 struct MLIRDocument {
260 StringRef contents, std::vector<lsp::Diagnostic> &diagnostics);
261 MLIRDocument(
const MLIRDocument &) =
delete;
262 MLIRDocument &operator=(
const MLIRDocument &) =
delete;
269 std::vector<lsp::Location> &locations);
271 std::vector<lsp::Location> &references);
279 std::optional<lsp::Hover>
280 buildHoverForOperation(SMRange hoverRange,
283 unsigned resultStart,
284 unsigned resultEnd, SMLoc posLoc);
285 lsp::Hover buildHoverForBlock(SMRange hoverRange,
288 buildHoverForBlockArgument(SMRange hoverRange,
BlockArgument arg,
294 buildHoverForTypeAlias(SMRange hoverRange,
301 void findDocumentSymbols(std::vector<lsp::DocumentSymbol> &symbols);
303 std::vector<lsp::DocumentSymbol> &symbols);
320 std::vector<lsp::TextEdit> &edits);
344 llvm::SourceMgr sourceMgr;
350 std::vector<lsp::Diagnostic> &diagnostics) {
356 auto memBuffer = llvm::MemoryBuffer::getMemBufferCopy(contents, uri.
file());
363 &fallbackResourceMap);
364 sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
380 std::vector<lsp::Location> &locations) {
387 locations.emplace_back(uri, sourceMgr, def.loc);
395 for (
const auto &result : op.resultGroups)
396 if (containsPosition(result.definition))
398 for (
const auto &symUse : op.symbolUses) {
400 locations.emplace_back(uri, sourceMgr, op.loc);
408 if (containsPosition(block.definition))
411 if (containsPosition(arg))
417 asmState.getAttributeAliasDefs()) {
418 if (containsPosition(attr.definition))
422 asmState.getTypeAliasDefs()) {
423 if (containsPosition(type.definition))
430 std::vector<lsp::Location> &references) {
434 references.emplace_back(uri, sourceMgr, def.loc);
435 for (
const SMRange &use : def.uses)
436 references.emplace_back(uri, sourceMgr, use);
444 for (
const auto &result : op.resultGroups)
445 appendSMDef(result.definition);
446 for (
const auto &symUse : op.symbolUses)
448 references.emplace_back(uri, sourceMgr, symUse);
451 for (
const auto &result : op.resultGroups)
453 return appendSMDef(result.definition);
454 for (
const auto &symUse : op.symbolUses) {
457 for (
const auto &symUse : op.symbolUses)
458 references.emplace_back(uri, sourceMgr, symUse);
466 return appendSMDef(block.definition);
470 return appendSMDef(arg);
475 asmState.getAttributeAliasDefs()) {
477 return appendSMDef(attr.definition);
480 asmState.getTypeAliasDefs()) {
482 return appendSMDef(type.definition);
490 std::optional<lsp::Hover>
493 SMLoc posLoc = hoverPos.
getAsSMLoc(sourceMgr);
500 return buildHoverForOperation(op.loc, op);
503 for (
auto &use : op.symbolUses)
505 return buildHoverForOperation(use, op);
508 for (
unsigned i = 0, e = op.resultGroups.size(); i < e; ++i) {
509 const auto &result = op.resultGroups[i];
510 if (!
isDefOrUse(result.definition, posLoc, &hoverRange))
514 unsigned resultStart = result.startIndex;
515 unsigned resultEnd = (i == e - 1) ? op.op->getNumResults()
516 : op.resultGroups[i + 1].startIndex;
517 return buildHoverForOperationResult(hoverRange, op.op, resultStart,
524 if (
isDefOrUse(block.definition, posLoc, &hoverRange))
525 return buildHoverForBlock(hoverRange, block);
528 if (!
isDefOrUse(arg.value(), posLoc, &hoverRange))
531 return buildHoverForBlockArgument(
532 hoverRange, block.block->
getArgument(arg.index()), block);
538 asmState.getAttributeAliasDefs()) {
539 if (
isDefOrUse(attr.definition, posLoc, &hoverRange))
540 return buildHoverForAttributeAlias(hoverRange, attr);
543 asmState.getTypeAliasDefs()) {
544 if (
isDefOrUse(type.definition, posLoc, &hoverRange))
545 return buildHoverForTypeAlias(hoverRange, type);
551 std::optional<lsp::Hover> MLIRDocument::buildHoverForOperation(
554 llvm::raw_string_ostream os(hover.contents.value);
558 if (SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op.
op))
559 os <<
" : " << symbol.getVisibility() <<
" @" << symbol.getName() <<
"";
562 os <<
"Generic Form:\n\n```mlir\n";
565 .printGenericOpForm()
566 .elideLargeElementsAttrs()
573 lsp::Hover MLIRDocument::buildHoverForOperationResult(SMRange hoverRange,
575 unsigned resultStart,
579 llvm::raw_string_ostream os(hover.contents.value);
582 os <<
"Operation: \"" << op->
getName() <<
"\"\n\n";
587 if ((resultStart + *resultNumber) < resultEnd) {
588 resultStart += *resultNumber;
589 resultEnd = resultStart + 1;
594 if ((resultStart + 1) == resultEnd) {
595 os <<
"Result #" << resultStart <<
"\n\n"
598 os <<
"Result #[" << resultStart <<
", " << (resultEnd - 1) <<
"]\n\n"
600 llvm::interleaveComma(
601 op->
getResults().slice(resultStart, resultEnd), os,
602 [&](
Value result) { os <<
"`" << result.getType() <<
"`"; });
609 MLIRDocument::buildHoverForBlock(SMRange hoverRange,
612 llvm::raw_string_ostream os(hover.contents.value);
615 auto printBlockToHover = [&](
Block *newBlock) {
616 if (
const auto *def = asmState.getBlockDef(newBlock))
626 os <<
"Predecessors: ";
632 os <<
"Successors: ";
640 lsp::Hover MLIRDocument::buildHoverForBlockArgument(
644 llvm::raw_string_ostream os(hover.contents.value);
651 <<
"Type: `" << arg.
getType() <<
"`\n\n";
656 lsp::Hover MLIRDocument::buildHoverForAttributeAlias(
659 llvm::raw_string_ostream os(hover.contents.value);
661 os <<
"Attribute Alias: \"" << attr.
name <<
"\n\n";
662 os <<
"Value: ```mlir\n" << attr.
value <<
"\n```\n\n";
667 lsp::Hover MLIRDocument::buildHoverForTypeAlias(
670 llvm::raw_string_ostream os(hover.contents.value);
672 os <<
"Type Alias: \"" << type.
name <<
"\n\n";
673 os <<
"Value: ```mlir\n" << type.
value <<
"\n```\n\n";
682 void MLIRDocument::findDocumentSymbols(
683 std::vector<lsp::DocumentSymbol> &symbols) {
685 findDocumentSymbols(&op, symbols);
688 void MLIRDocument::findDocumentSymbols(
689 Operation *op, std::vector<lsp::DocumentSymbol> &symbols) {
690 std::vector<lsp::DocumentSymbol> *childSymbols = &symbols;
695 if (SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op)) {
696 symbols.emplace_back(symbol.getName(),
697 isa<FunctionOpInterface>(op)
702 childSymbols = &symbols.back().children;
710 childSymbols = &symbols.back().children;
718 for (
Operation &childOp : region.getOps())
719 findDocumentSymbols(&childOp, *childSymbols);
732 completionList(completionList), ctx(ctx) {}
735 void completeDialectName(StringRef prefix)
final {
736 for (StringRef dialect : ctx->getAvailableDialects()) {
740 item.detail =
"dialect";
741 completionList.items.emplace_back(item);
747 void completeOperationName(StringRef dialectName)
final {
748 Dialect *dialect = ctx->getOrLoadDialect(dialectName);
752 for (
const auto &op : ctx->getRegisteredOperations()) {
757 op.getStringRef().drop_front(dialectName.size() + 1),
760 item.detail =
"operation";
761 completionList.items.emplace_back(item);
767 void appendSSAValueCompletion(StringRef name, std::string typeData)
final {
769 bool stripPrefix = getCodeCompleteLoc().getPointer()[-1] ==
'%';
773 item.insertText = name.drop_front(1).str();
774 item.detail = std::move(typeData);
775 completionList.items.emplace_back(item);
780 void appendBlockCompletion(StringRef name)
final {
782 bool stripPrefix = getCodeCompleteLoc().getPointer()[-1] ==
'^';
786 item.insertText = name.drop_front(1).str();
787 completionList.items.emplace_back(item);
792 for (StringRef token : tokens) {
795 item.detail = optional ?
"optional" :
"";
796 completionList.items.emplace_back(item);
801 void completeAttribute(
const llvm::StringMap<Attribute> &aliases)
override {
802 appendSimpleCompletions({
"affine_set",
"affine_map",
"dense",
803 "dense_resource",
"false",
"loc",
"sparse",
"true",
808 completeDialectName(
"#");
809 completeAliases(aliases,
"#");
811 void completeDialectAttributeOrAlias(
812 const llvm::StringMap<Attribute> &aliases)
override {
813 completeDialectName();
814 completeAliases(aliases);
818 void completeType(
const llvm::StringMap<Type> &aliases)
override {
820 appendSimpleCompletions({
"memref",
"tensor",
"complex",
"tuple",
"vector",
821 "bf16",
"f16",
"f32",
"f64",
"f80",
"f128",
827 for (StringRef type : {
"i",
"si",
"ui"}) {
830 item.insertText = type.str();
831 completionList.items.emplace_back(item);
835 completeDialectName(
"!");
836 completeAliases(aliases,
"!");
839 completeDialectTypeOrAlias(
const llvm::StringMap<Type> &aliases)
override {
840 completeDialectName();
841 completeAliases(aliases);
845 template <
typename T>
846 void completeAliases(
const llvm::StringMap<T> &aliases,
847 StringRef prefix =
"") {
848 for (
const auto &alias : aliases) {
852 llvm::raw_string_ostream(item.detail) <<
"alias: " << alias.getValue();
853 completionList.items.emplace_back(item);
860 StringRef sortText =
"") {
861 for (StringRef completion : completions)
862 completionList.items.emplace_back(completion, kind, sortText);
875 SMLoc posLoc = completePos.
getAsSMLoc(sourceMgr);
876 if (!posLoc.isValid())
882 tmpContext.allowUnregisteredDialects();
884 LSPCodeCompleteContext lspCompleteContext(posLoc, completionList,
890 &lspCompleteContext);
891 return completionList;
898 void MLIRDocument::getCodeActionForDiagnostic(
900 StringRef message, std::vector<lsp::TextEdit> &edits) {
904 if (message.starts_with(
"see current operation: "))
908 const auto &buffer = sourceMgr.getBufferInfo(sourceMgr.getMainFileID());
909 const char *lineStart = buffer.getPointerForLineNumber(pos.
line + 1);
912 StringRef line(lineStart, pos.
character);
920 size_t indent = line.find_first_not_of(
' ');
921 if (indent == StringRef::npos)
922 indent = line.size();
924 edit.
newText.append(indent,
' ');
925 llvm::raw_string_ostream(edit.
newText)
926 <<
"// expected-" << severity <<
" @below {{" << message <<
"}}\n";
927 edits.emplace_back(std::move(edit));
935 MLIRDocument::convertToBytecode() {
938 if (!llvm::hasSingleElement(parsedIR)) {
939 if (parsedIR.empty()) {
940 return llvm::make_error<lsp::LSPError>(
941 "expected a single and valid top-level operation, please ensure "
942 "there are no errors",
945 return llvm::make_error<lsp::LSPError>(
953 std::string rawBytecodeBuffer;
954 llvm::raw_string_ostream os(rawBytecodeBuffer);
957 result.
output = llvm::encodeBase64(rawBytecodeBuffer);
968 struct MLIRTextFileChunk {
969 MLIRTextFileChunk(
MLIRContext &context, uint64_t lineOffset,
971 std::vector<lsp::Diagnostic> &diagnostics)
972 : lineOffset(lineOffset), document(context, uri, contents, diagnostics) {}
976 void adjustLocForChunkOffset(
lsp::Range &range) {
977 adjustLocForChunkOffset(range.
start);
978 adjustLocForChunkOffset(range.
end);
987 MLIRDocument document;
1001 std::vector<lsp::Diagnostic> &diagnostics);
1004 int64_t getVersion()
const {
return version; }
1011 std::vector<lsp::Location> &locations);
1013 std::vector<lsp::Location> &references);
1016 void findDocumentSymbols(std::vector<lsp::DocumentSymbol> &symbols);
1021 std::vector<lsp::CodeAction> &actions);
1034 std::string contents;
1040 int64_t totalNumLines = 0;
1044 std::vector<std::unique_ptr<MLIRTextFileChunk>> chunks;
1048 MLIRTextFile::MLIRTextFile(
const lsp::URIForFile &uri, StringRef fileContents,
1050 std::vector<lsp::Diagnostic> &diagnostics)
1051 : context(registry,
MLIRContext::Threading::DISABLED),
1052 contents(fileContents.str()), version(version) {
1058 chunks.emplace_back(std::make_unique<MLIRTextFileChunk>(
1059 context, 0, uri, subContents.front(), diagnostics));
1061 uint64_t lineOffset = subContents.front().count(
'\n');
1062 for (StringRef docContents : llvm::drop_begin(subContents)) {
1063 unsigned currentNumDiags = diagnostics.size();
1064 auto chunk = std::make_unique<MLIRTextFileChunk>(context, lineOffset, uri,
1065 docContents, diagnostics);
1066 lineOffset += docContents.count(
'\n');
1071 llvm::drop_begin(diagnostics, currentNumDiags)) {
1072 chunk->adjustLocForChunkOffset(
diag.range);
1074 if (!
diag.relatedInformation)
1076 for (
auto &it : *
diag.relatedInformation)
1077 if (it.location.uri == uri)
1078 chunk->adjustLocForChunkOffset(it.location.range);
1080 chunks.emplace_back(std::move(chunk));
1082 totalNumLines = lineOffset;
1087 std::vector<lsp::Location> &locations) {
1088 MLIRTextFileChunk &chunk = getChunkFor(defPos);
1089 chunk.document.getLocationsOf(uri, defPos, locations);
1092 if (chunk.lineOffset == 0)
1096 chunk.adjustLocForChunkOffset(loc.range);
1101 std::vector<lsp::Location> &references) {
1102 MLIRTextFileChunk &chunk = getChunkFor(pos);
1103 chunk.document.findReferencesOf(uri, pos, references);
1106 if (chunk.lineOffset == 0)
1110 chunk.adjustLocForChunkOffset(loc.range);
1113 std::optional<lsp::Hover> MLIRTextFile::findHover(
const lsp::URIForFile &uri,
1115 MLIRTextFileChunk &chunk = getChunkFor(hoverPos);
1116 std::optional<lsp::Hover> hoverInfo = chunk.document.findHover(uri, hoverPos);
1119 if (chunk.lineOffset != 0 && hoverInfo && hoverInfo->range)
1120 chunk.adjustLocForChunkOffset(*hoverInfo->range);
1124 void MLIRTextFile::findDocumentSymbols(
1125 std::vector<lsp::DocumentSymbol> &symbols) {
1126 if (chunks.size() == 1)
1127 return chunks.front()->document.findDocumentSymbols(symbols);
1131 for (
unsigned i = 0, e = chunks.size(); i < e; ++i) {
1132 MLIRTextFileChunk &chunk = *chunks[i];
1135 : chunks[i + 1]->lineOffset);
1137 lsp::SymbolKind::Namespace,
1140 chunk.document.findDocumentSymbols(symbol.children);
1146 symbolsToFix.push_back(&childSymbol);
1148 while (!symbolsToFix.empty()) {
1150 chunk.adjustLocForChunkOffset(symbol->
range);
1154 symbolsToFix.push_back(&childSymbol);
1159 symbols.emplace_back(std::move(symbol));
1165 MLIRTextFileChunk &chunk = getChunkFor(completePos);
1172 chunk.adjustLocForChunkOffset(item.
textEdit->range);
1174 chunk.adjustLocForChunkOffset(edit.
range);
1176 return completionList;
1182 std::vector<lsp::CodeAction> &actions) {
1185 if (
diag.source !=
"mlir")
1188 MLIRTextFileChunk &chunk = getChunkFor(diagPos);
1192 action.
title =
"Add expected-* diagnostic checks";
1193 action.
kind = lsp::CodeAction::kQuickFix.str();
1196 switch (
diag.severity) {
1200 case lsp::DiagnosticSeverity::Warning:
1201 severity =
"warning";
1208 std::vector<lsp::TextEdit> edits;
1209 chunk.document.getCodeActionForDiagnostic(uri, diagPos, severity,
1210 diag.message, edits);
1213 if (
diag.relatedInformation) {
1214 for (
auto ¬eDiag : *
diag.relatedInformation) {
1215 if (noteDiag.location.uri != uri)
1217 diagPos = noteDiag.location.range.start;
1218 diagPos.
line -= chunk.lineOffset;
1219 chunk.document.getCodeActionForDiagnostic(uri, diagPos,
"note",
1220 noteDiag.message, edits);
1225 chunk.adjustLocForChunkOffset(edit.
range);
1227 action.
edit.emplace();
1228 action.
edit->changes[uri.
uri().str()] = std::move(edits);
1231 actions.emplace_back(std::move(action));
1236 MLIRTextFile::convertToBytecode() {
1238 if (chunks.size() != 1) {
1239 return llvm::make_error<lsp::LSPError>(
1240 "unexpected split file, please remove all `// -----`",
1241 lsp::ErrorCode::RequestFailed);
1243 return chunks.front()->document.convertToBytecode();
1246 MLIRTextFileChunk &MLIRTextFile::getChunkFor(
lsp::Position &pos) {
1247 if (chunks.size() == 1)
1248 return *chunks.front();
1252 auto it = llvm::upper_bound(
1253 chunks, pos, [](
const lsp::Position &pos,
const auto &chunk) {
1254 return static_cast<uint64_t
>(pos.
line) < chunk->lineOffset;
1256 MLIRTextFileChunk &chunk = it == chunks.end() ? *chunks.back() : **(--it);
1257 pos.
line -= chunk.lineOffset;
1273 llvm::StringMap<std::unique_ptr<MLIRTextFile>>
files;
1281 :
impl(std::make_unique<
Impl>(registry)) {}
1285 const URIForFile &uri, StringRef contents, int64_t version,
1286 std::vector<Diagnostic> &diagnostics) {
1287 impl->files[uri.
file()] = std::make_unique<MLIRTextFile>(
1288 uri, contents, version,
impl->registry, diagnostics);
1292 auto it =
impl->files.find(uri.
file());
1293 if (it ==
impl->files.end())
1294 return std::nullopt;
1296 int64_t version = it->second->getVersion();
1297 impl->files.erase(it);
1303 std::vector<Location> &locations) {
1304 auto fileIt =
impl->files.find(uri.
file());
1305 if (fileIt !=
impl->files.end())
1306 fileIt->second->getLocationsOf(uri, defPos, locations);
1311 std::vector<Location> &references) {
1312 auto fileIt =
impl->files.find(uri.
file());
1313 if (fileIt !=
impl->files.end())
1314 fileIt->second->findReferencesOf(uri, pos, references);
1319 auto fileIt =
impl->files.find(uri.
file());
1320 if (fileIt !=
impl->files.end())
1321 return fileIt->second->findHover(uri, hoverPos);
1322 return std::nullopt;
1326 const URIForFile &uri, std::vector<DocumentSymbol> &symbols) {
1327 auto fileIt =
impl->files.find(uri.
file());
1328 if (fileIt !=
impl->files.end())
1329 fileIt->second->findDocumentSymbols(symbols);
1335 auto fileIt =
impl->files.find(uri.
file());
1336 if (fileIt !=
impl->files.end())
1337 return fileIt->second->getCodeCompletion(uri, completePos);
1343 std::vector<CodeAction> &actions) {
1344 auto fileIt =
impl->files.find(uri.
file());
1345 if (fileIt !=
impl->files.end())
1346 fileIt->second->getCodeActions(uri, pos, context, actions);
1355 std::string errorMsg;
1365 &fallbackResourceMap);
1370 return llvm::make_error<lsp::LSPError>(
1371 "failed to parse bytecode source file: " + errorMsg,
1377 if (!llvm::hasSingleElement(parsedBlock)) {
1378 return llvm::make_error<lsp::LSPError>(
1379 "expected bytecode to contain a single top-level operation",
1392 nullptr, &fallbackResourceMap);
1394 llvm::raw_string_ostream os(result.
output);
1395 topOp->print(os, state);
1397 return std::move(result);
1402 auto fileIt =
impl->files.find(uri.
file());
1403 if (fileIt ==
impl->files.end()) {
1404 return llvm::make_error<lsp::LSPError>(
1405 "language server does not contain an entry for this source file",
1408 return fileIt->second->convertToBytecode();
static std::string toString(bytecode::Section::ID sectionID)
Stringify the given section ID.
static void collectLocationsFromLoc(Location loc, std::vector< lsp::Location > &locations, const lsp::URIForFile &uri)
Collect all of the locations from the given MLIR location that are not contained within the given URI...
static unsigned getBlockNumber(Block *block)
Given a block, return its position in its parent region.
static std::optional< lsp::Location > getLocationFromLoc(StringRef uriScheme, FileLineColLoc loc)
Returns a language server location from the given MLIR file location.
static bool isDefOrUse(const AsmParserState::SMDefinition &def, SMLoc loc, SMRange *overlappedRange=nullptr)
Returns true if the given location is contained by the definition or one of the uses of the given SMD...
static bool contains(SMRange range, SMLoc loc)
Returns true if the given range contains the given source location.
static lsp::Diagnostic getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr, Diagnostic &diag, const lsp::URIForFile &uri)
Convert the given MLIR diagnostic to the LSP form.
static void printDefBlockName(raw_ostream &os, Block *block, SMRange loc={})
Given a block and source location, print the source name of the block to the given output stream.
static std::optional< unsigned > getResultNumberFromLoc(SMLoc loc)
Given a location pointing to a result, return the result number it refers to or std::nullopt if it re...
static SMRange convertTokenLocToRange(SMLoc loc)
Returns the range of a lexical token given a SMLoc corresponding to the start of an token location.
static std::optional< StringRef > getTextFromRange(SMRange range)
Given a source location range, return the text covered by the given range.
static std::string diag(const llvm::Value &value)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
This class provides an abstract interface into the parser for hooking in code completion events.
void completeDialectName()
This class represents state from a parsed MLIR textual format string.
This class provides management for the lifetime of the state used when printing the IR.
This class represents an argument of a Block.
unsigned getArgNumber() const
Returns the number of this argument.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
bool hasNoSuccessors()
Returns true if this blocks has no successors.
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
SuccessorRange getSuccessors()
iterator_range< pred_iterator > getPredecessors()
bool hasNoPredecessors()
Return true if this block has no predecessors.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
This class contains the configuration used for the bytecode writer.
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
A fallback map containing external resources not explicitly handled by another parser/printer.
WalkResult walk(function_ref< WalkResult(Location)> walkFn)
Walk all of the locations nested directly under, and including, the current.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
const DialectRegistry & getDialectRegistry()
Return the dialect registry associated with this context.
void allowUnregisteredDialects(bool allow=true)
Enables creating operations in unregistered dialects.
Set of flags used to control the behavior of the various IR print methods (e.g.
A trait used to provide symbol table functionalities to a region operation.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
void print(raw_ostream &os, const OpPrintingFlags &flags=std::nullopt)
unsigned getNumRegions()
Returns the number of regions held by this operation.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
OperationName getName()
The name of an operation is the key identifier for it.
result_range getResults()
This class acts as an owning reference to an op, and will automatically destroy the held op on destru...
This class represents a configuration for the MLIR assembly parser.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This diagnostic handler is a simple RAII class that registers and erases a diagnostic handler on a gi...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
static WalkResult advance()
static WalkResult interrupt()
static void error(const char *fmt, Ts &&...vals)
void addOrUpdateDocument(const URIForFile &uri, StringRef contents, int64_t version, std::vector< Diagnostic > &diagnostics)
Add or update the document, with the provided version, at the given URI.
std::optional< int64_t > removeDocument(const URIForFile &uri)
Remove the document with the given uri.
void findReferencesOf(const URIForFile &uri, const Position &pos, std::vector< Location > &references)
Find all references of the object pointed at by the given position.
void getLocationsOf(const URIForFile &uri, const Position &defPos, std::vector< Location > &locations)
Return the locations of the object pointed at by the given position.
std::optional< Hover > findHover(const URIForFile &uri, const Position &hoverPos)
Find a hover description for the given hover position, or std::nullopt if one couldn't be found.
llvm::Expected< MLIRConvertBytecodeResult > convertFromBytecode(const URIForFile &uri)
Convert the given bytecode file to the textual format.
llvm::Expected< MLIRConvertBytecodeResult > convertToBytecode(const URIForFile &uri)
Convert the given textual file to the bytecode format.
CompletionList getCodeCompletion(const URIForFile &uri, const Position &completePos)
Get the code completion list for the position within the given file.
void findDocumentSymbols(const URIForFile &uri, std::vector< DocumentSymbol > &symbols)
Find all of the document symbols within the given file.
void getCodeActions(const URIForFile &uri, const Range &pos, const CodeActionContext &context, std::vector< CodeAction > &actions)
Get the set of code actions within the file.
URI in "file" scheme for a file.
StringRef uri() const
Returns the original uri of the file.
static llvm::Expected< URIForFile > fromFile(StringRef absoluteFilepath, StringRef scheme="file")
Try to build a URIForFile from the given absolute file path and optional scheme.
StringRef scheme() const
Return the scheme of the uri.
StringRef file() const
Returns the absolute path to the file.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
SMRange convertTokenLocToRange(SMLoc loc, StringRef identifierChars="")
Returns the range of a lexical token given a SMLoc corresponding to the start of an token location.
CompletionItemKind
The kind of a completion entry.
Include the generated interface declarations.
const char *const kDefaultSplitMarker
LogicalResult parseAsmSourceFile(const llvm::SourceMgr &sourceMgr, Block *block, const ParserConfig &config, AsmParserState *asmState=nullptr, AsmParserCodeCompleteContext *codeCompleteContext=nullptr)
This parses the file specified by the indicated SourceMgr and appends parsed operations to the given ...
LogicalResult parseSourceFile(const llvm::SourceMgr &sourceMgr, Block *block, const ParserConfig &config, LocationAttr *sourceFileLoc=nullptr)
This parses the file specified by the indicated SourceMgr and appends parsed operations to the given ...
LogicalResult writeBytecodeToFile(Operation *op, raw_ostream &os, const BytecodeWriterConfig &config={})
Write the bytecode for the given operation to the provided output stream.
Impl(DialectRegistry ®istry)
DialectRegistry & registry
The registry containing dialects that can be recognized in parsed .mlir files.
llvm::StringMap< std::unique_ptr< MLIRTextFile > > files
The files held by the server, mapped by their URI file name.
This class represents the information for an attribute alias definition within the input file.
StringRef name
The name of the attribute alias.
Attribute value
The value of the alias.
This class represents the information for a block definition within the input file.
Block * block
The block representing this definition.
SMDefinition definition
The source location for the block, i.e.
This class represents the information for an operation definition within an input file.
Operation * op
The operation representing this definition.
This class represents a definition within the source manager, containing it's defining location and l...
SmallVector< SMRange > uses
The source location of all uses of the definition.
SMRange loc
The source location of the definition.
This class represents the information for type definition within the input file.
Type value
The value of the alias.
StringRef name
The name of the attribute alias.
std::vector< Diagnostic > diagnostics
An array of diagnostics known on the client side overlapping the range provided to the textDocument/c...
A code action represents a change that can be performed in code, e.g.
std::optional< WorkspaceEdit > edit
The workspace edit this code action performs.
std::optional< std::string > kind
The kind of the code action.
std::optional< std::vector< Diagnostic > > diagnostics
The diagnostics that this code action resolves.
std::string title
A short, human-readable, title for this code action.
std::optional< TextEdit > textEdit
An edit which is applied to a document when selecting this completion.
std::vector< TextEdit > additionalTextEdits
An optional array of additional text edits that are applied when selecting this completion.
Represents a collection of completion items to be presented in the editor.
std::vector< CompletionItem > items
The completion items.
std::string source
A human-readable string describing the source of this diagnostic, e.g.
DiagnosticSeverity severity
The diagnostic's severity.
Range range
The source range where the message applies.
std::optional< std::vector< DiagnosticRelatedInformation > > relatedInformation
An array of related diagnostic information, e.g.
std::string message
The diagnostic's message.
std::optional< std::string > category
The diagnostic's category.
Represents programming constructs like variables, classes, interfaces etc.
Range range
The range enclosing this symbol not including leading/trailing whitespace but everything else like co...
Range selectionRange
The range that should be selected and revealed when this symbol is being picked, e....
std::vector< DocumentSymbol > children
Children of this symbol, e.g. properties of a class.
URIForFile uri
The text document's URI.
This class represents the result of converting between MLIR's bytecode and textual format.
std::string output
The resultant output of the conversion.
int line
Line position in a document (zero-based).
int character
Character offset on a line in a document (zero-based).
SMLoc getAsSMLoc(llvm::SourceMgr &mgr) const
Convert this position into a source location in the main file of the given source manager.
Position end
The range's end position.
Position start
The range's start position.
std::string newText
The string to be inserted.
Range range
The range of the text document to be manipulated.