20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/Support/Base64.h"
22 #include "llvm/Support/SourceMgr.h"
48 position.
line = loc.getLine() - 1;
49 position.
character = loc.getColumn() ? loc.getColumn() - 1 : 0;
57 static std::optional<lsp::Location>
60 std::optional<lsp::Location> location;
62 FileLineColLoc fileLoc = dyn_cast<FileLineColLoc>(nestedLoc);
66 std::optional<lsp::Location> sourceLoc =
68 if (sourceLoc && (!uri || sourceLoc->uri == *uri)) {
69 location = *sourceLoc;
70 SMLoc loc = sourceMgr.FindLocForLineAndColumn(
71 sourceMgr.getMainFileID(), fileLoc.getLine(), fileLoc.getColumn());
75 location->range.end.character += 1;
77 auto lineCol = sourceMgr.getLineAndColumn(range->End);
78 location->range.end.character =
79 std::max(fileLoc.getColumn() + 1, lineCol.second - 1);
91 std::vector<lsp::Location> &locations,
95 FileLineColLoc fileLoc = dyn_cast<FileLineColLoc>(nestedLoc);
96 if (!fileLoc || !visitedLocs.insert(nestedLoc))
99 std::optional<lsp::Location> sourceLoc =
101 if (sourceLoc && sourceLoc->uri != uri)
102 locations.push_back(*sourceLoc);
111 return range.Start.getPointer() <= loc.getPointer() &&
112 loc.getPointer() <= range.End.getPointer();
119 SMRange *overlappedRange =
nullptr) {
123 *overlappedRange = def.
loc;
128 const auto *useIt = llvm::find_if(
129 def.
uses, [&](
const SMRange &range) { return contains(range, loc); });
130 if (useIt != def.
uses.end()) {
132 *overlappedRange = *useIt;
142 auto isIdentifierChar = [](
char c) {
143 return isalnum(c) || c ==
'%' || c ==
'$' || c ==
'.' || c ==
'_' ||
146 const char *curPtr = loc.getPointer();
147 while (isIdentifierChar(*curPtr))
156 const char *numberStart = ++curPtr;
157 while (llvm::isDigit(*curPtr))
159 StringRef numberStr(numberStart, curPtr - numberStart);
160 unsigned resultNumber = 0;
161 return numberStr.consumeInteger(10, resultNumber) ? std::optional<unsigned>()
168 if (!range.isValid())
170 const char *startPtr = range.Start.getPointer();
171 return StringRef(startPtr, range.End.getPointer() - startPtr);
176 return std::distance(block->
getParent()->
begin(), block->getIterator());
184 if (text && text->startswith(
"^")) {
211 StringRef uriScheme = uri.
scheme();
212 std::optional<lsp::Location> lspLocation =
215 lspDiag.
range = lspLocation->range;
218 switch (
diag.getSeverity()) {
220 llvm_unreachable(
"expected notes to be handled separately");
234 std::vector<lsp::DiagnosticRelatedInformation> relatedDiags;
237 if (std::optional<lsp::Location> loc =
242 relatedDiags.emplace_back(noteLoc, note.str());
244 if (!relatedDiags.empty())
257 struct MLIRDocument {
259 StringRef contents, std::vector<lsp::Diagnostic> &diagnostics);
260 MLIRDocument(
const MLIRDocument &) =
delete;
261 MLIRDocument &operator=(
const MLIRDocument &) =
delete;
268 std::vector<lsp::Location> &locations);
270 std::vector<lsp::Location> &references);
278 std::optional<lsp::Hover>
279 buildHoverForOperation(SMRange hoverRange,
282 unsigned resultStart,
283 unsigned resultEnd, SMLoc posLoc);
284 lsp::Hover buildHoverForBlock(SMRange hoverRange,
287 buildHoverForBlockArgument(SMRange hoverRange,
BlockArgument arg,
293 buildHoverForTypeAlias(SMRange hoverRange,
300 void findDocumentSymbols(std::vector<lsp::DocumentSymbol> &symbols);
302 std::vector<lsp::DocumentSymbol> &symbols);
319 std::vector<lsp::TextEdit> &edits);
343 llvm::SourceMgr sourceMgr;
349 std::vector<lsp::Diagnostic> &diagnostics) {
355 auto memBuffer = llvm::MemoryBuffer::getMemBufferCopy(contents, uri.
file());
362 &fallbackResourceMap);
363 sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
379 std::vector<lsp::Location> &locations) {
386 locations.emplace_back(uri, sourceMgr, def.loc);
394 for (
const auto &result : op.resultGroups)
395 if (containsPosition(result.definition))
397 for (
const auto &symUse : op.symbolUses) {
399 locations.emplace_back(uri, sourceMgr, op.loc);
407 if (containsPosition(block.definition))
410 if (containsPosition(arg))
416 asmState.getAttributeAliasDefs()) {
417 if (containsPosition(attr.definition))
421 asmState.getTypeAliasDefs()) {
422 if (containsPosition(type.definition))
429 std::vector<lsp::Location> &references) {
433 references.emplace_back(uri, sourceMgr, def.loc);
434 for (
const SMRange &use : def.uses)
435 references.emplace_back(uri, sourceMgr, use);
443 for (
const auto &result : op.resultGroups)
444 appendSMDef(result.definition);
445 for (
const auto &symUse : op.symbolUses)
447 references.emplace_back(uri, sourceMgr, symUse);
450 for (
const auto &result : op.resultGroups)
452 return appendSMDef(result.definition);
453 for (
const auto &symUse : op.symbolUses) {
456 for (
const auto &symUse : op.symbolUses)
457 references.emplace_back(uri, sourceMgr, symUse);
465 return appendSMDef(block.definition);
469 return appendSMDef(arg);
474 asmState.getAttributeAliasDefs()) {
476 return appendSMDef(attr.definition);
479 asmState.getTypeAliasDefs()) {
481 return appendSMDef(type.definition);
489 std::optional<lsp::Hover>
492 SMLoc posLoc = hoverPos.
getAsSMLoc(sourceMgr);
499 return buildHoverForOperation(op.loc, op);
502 for (
auto &use : op.symbolUses)
504 return buildHoverForOperation(use, op);
507 for (
unsigned i = 0, e = op.resultGroups.size(); i < e; ++i) {
508 const auto &result = op.resultGroups[i];
509 if (!
isDefOrUse(result.definition, posLoc, &hoverRange))
513 unsigned resultStart = result.startIndex;
515 : op.resultGroups[i + 1].startIndex;
516 return buildHoverForOperationResult(hoverRange, op.op, resultStart,
523 if (
isDefOrUse(block.definition, posLoc, &hoverRange))
524 return buildHoverForBlock(hoverRange, block);
527 if (!
isDefOrUse(arg.value(), posLoc, &hoverRange))
530 return buildHoverForBlockArgument(
531 hoverRange, block.block->
getArgument(arg.index()), block);
537 asmState.getAttributeAliasDefs()) {
538 if (
isDefOrUse(attr.definition, posLoc, &hoverRange))
539 return buildHoverForAttributeAlias(hoverRange, attr);
542 asmState.getTypeAliasDefs()) {
543 if (
isDefOrUse(type.definition, posLoc, &hoverRange))
544 return buildHoverForTypeAlias(hoverRange, type);
550 std::optional<lsp::Hover> MLIRDocument::buildHoverForOperation(
553 llvm::raw_string_ostream os(hover.contents.value);
556 os <<
"\"" << op.op->
getName() <<
"\"";
557 if (SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op.op))
558 os <<
" : " << symbol.getVisibility() <<
" @" << symbol.getName() <<
"";
561 os <<
"Generic Form:\n\n```mlir\n";
564 .printGenericOpForm()
565 .elideLargeElementsAttrs()
572 lsp::Hover MLIRDocument::buildHoverForOperationResult(SMRange hoverRange,
574 unsigned resultStart,
578 llvm::raw_string_ostream os(hover.contents.value);
581 os <<
"Operation: \"" << op->
getName() <<
"\"\n\n";
586 if ((resultStart + *resultNumber) < resultEnd) {
587 resultStart += *resultNumber;
588 resultEnd = resultStart + 1;
593 if ((resultStart + 1) == resultEnd) {
594 os <<
"Result #" << resultStart <<
"\n\n"
597 os <<
"Result #[" << resultStart <<
", " << (resultEnd - 1) <<
"]\n\n"
599 llvm::interleaveComma(
600 op->
getResults().slice(resultStart, resultEnd), os,
601 [&](
Value result) { os <<
"`" << result.getType() <<
"`"; });
608 MLIRDocument::buildHoverForBlock(SMRange hoverRange,
611 llvm::raw_string_ostream os(hover.contents.value);
614 auto printBlockToHover = [&](
Block *newBlock) {
615 if (
const auto *def = asmState.getBlockDef(newBlock))
625 os <<
"Predecessors: ";
631 os <<
"Successors: ";
639 lsp::Hover MLIRDocument::buildHoverForBlockArgument(
643 llvm::raw_string_ostream os(hover.contents.value);
650 <<
"Type: `" << arg.
getType() <<
"`\n\n";
655 lsp::Hover MLIRDocument::buildHoverForAttributeAlias(
658 llvm::raw_string_ostream os(hover.contents.value);
660 os <<
"Attribute Alias: \"" << attr.
name <<
"\n\n";
661 os <<
"Value: ```mlir\n" << attr.
value <<
"\n```\n\n";
666 lsp::Hover MLIRDocument::buildHoverForTypeAlias(
669 llvm::raw_string_ostream os(hover.contents.value);
671 os <<
"Type Alias: \"" << type.
name <<
"\n\n";
672 os <<
"Value: ```mlir\n" << type.
value <<
"\n```\n\n";
681 void MLIRDocument::findDocumentSymbols(
682 std::vector<lsp::DocumentSymbol> &symbols) {
684 findDocumentSymbols(&op, symbols);
687 void MLIRDocument::findDocumentSymbols(
688 Operation *op, std::vector<lsp::DocumentSymbol> &symbols) {
689 std::vector<lsp::DocumentSymbol> *childSymbols = &symbols;
694 if (SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op)) {
695 symbols.emplace_back(symbol.getName(),
696 isa<FunctionOpInterface>(op)
701 childSymbols = &symbols.back().children;
709 childSymbols = &symbols.back().children;
717 for (
Operation &childOp : region.getOps())
718 findDocumentSymbols(&childOp, *childSymbols);
731 completionList(completionList), ctx(ctx) {}
734 void completeDialectName(StringRef prefix)
final {
735 for (StringRef dialect : ctx->getAvailableDialects()) {
739 item.detail =
"dialect";
740 completionList.items.emplace_back(item);
746 void completeOperationName(StringRef dialectName)
final {
747 Dialect *dialect = ctx->getOrLoadDialect(dialectName);
751 for (
const auto &op : ctx->getRegisteredOperations()) {
756 op.getStringRef().drop_front(dialectName.size() + 1),
759 item.detail =
"operation";
760 completionList.items.emplace_back(item);
766 void appendSSAValueCompletion(StringRef name, std::string typeData)
final {
768 bool stripPrefix = getCodeCompleteLoc().getPointer()[-1] ==
'%';
772 item.insertText = name.drop_front(1).str();
773 item.detail = std::move(typeData);
774 completionList.items.emplace_back(item);
779 void appendBlockCompletion(StringRef name)
final {
781 bool stripPrefix = getCodeCompleteLoc().getPointer()[-1] ==
'^';
785 item.insertText = name.drop_front(1).str();
786 completionList.items.emplace_back(item);
791 for (StringRef token : tokens) {
794 item.detail = optional ?
"optional" :
"";
795 completionList.items.emplace_back(item);
800 void completeAttribute(
const llvm::StringMap<Attribute> &aliases)
override {
801 appendSimpleCompletions({
"affine_set",
"affine_map",
"dense",
802 "dense_resource",
"false",
"loc",
"sparse",
"true",
807 completeDialectName(
"#");
808 completeAliases(aliases,
"#");
810 void completeDialectAttributeOrAlias(
811 const llvm::StringMap<Attribute> &aliases)
override {
812 completeDialectName();
813 completeAliases(aliases);
817 void completeType(
const llvm::StringMap<Type> &aliases)
override {
819 appendSimpleCompletions({
"memref",
"tensor",
"complex",
"tuple",
"vector",
820 "bf16",
"f16",
"f32",
"f64",
"f80",
"f128",
826 for (StringRef type : {
"i",
"si",
"ui"}) {
829 item.insertText = type.str();
830 completionList.items.emplace_back(item);
834 completeDialectName(
"!");
835 completeAliases(aliases,
"!");
838 completeDialectTypeOrAlias(
const llvm::StringMap<Type> &aliases)
override {
839 completeDialectName();
840 completeAliases(aliases);
844 template <
typename T>
845 void completeAliases(
const llvm::StringMap<T> &aliases,
846 StringRef prefix =
"") {
847 for (
const auto &alias : aliases) {
851 llvm::raw_string_ostream(item.detail) <<
"alias: " << alias.getValue();
852 completionList.items.emplace_back(item);
859 StringRef sortText =
"") {
860 for (StringRef completion : completions)
861 completionList.items.emplace_back(completion, kind, sortText);
874 SMLoc posLoc = completePos.
getAsSMLoc(sourceMgr);
875 if (!posLoc.isValid())
881 tmpContext.allowUnregisteredDialects();
883 LSPCodeCompleteContext lspCompleteContext(posLoc, completionList,
889 &lspCompleteContext);
890 return completionList;
897 void MLIRDocument::getCodeActionForDiagnostic(
899 StringRef message, std::vector<lsp::TextEdit> &edits) {
903 if (message.startswith(
"see current operation: "))
907 const auto &buffer = sourceMgr.getBufferInfo(sourceMgr.getMainFileID());
908 const char *lineStart = buffer.getPointerForLineNumber(pos.
line + 1);
911 StringRef line(lineStart, pos.
character);
919 size_t indent = line.find_first_not_of(
" ");
920 if (indent == StringRef::npos)
921 indent = line.size();
923 edit.
newText.append(indent,
' ');
924 llvm::raw_string_ostream(edit.
newText)
925 <<
"// expected-" << severity <<
" @below {{" << message <<
"}}\n";
926 edits.emplace_back(std::move(edit));
934 MLIRDocument::convertToBytecode() {
937 if (!llvm::hasSingleElement(parsedIR)) {
938 if (parsedIR.empty()) {
939 return llvm::make_error<lsp::LSPError>(
940 "expected a single and valid top-level operation, please ensure "
941 "there are no errors",
944 return llvm::make_error<lsp::LSPError>(
952 std::string rawBytecodeBuffer;
953 llvm::raw_string_ostream os(rawBytecodeBuffer);
956 result.
output = llvm::encodeBase64(rawBytecodeBuffer);
967 struct MLIRTextFileChunk {
968 MLIRTextFileChunk(
MLIRContext &context, uint64_t lineOffset,
970 std::vector<lsp::Diagnostic> &diagnostics)
971 : lineOffset(lineOffset), document(context, uri, contents, diagnostics) {}
975 void adjustLocForChunkOffset(
lsp::Range &range) {
976 adjustLocForChunkOffset(range.
start);
977 adjustLocForChunkOffset(range.
end);
986 MLIRDocument document;
1000 std::vector<lsp::Diagnostic> &diagnostics);
1003 int64_t getVersion()
const {
return version; }
1010 std::vector<lsp::Location> &locations);
1012 std::vector<lsp::Location> &references);
1015 void findDocumentSymbols(std::vector<lsp::DocumentSymbol> &symbols);
1020 std::vector<lsp::CodeAction> &actions);
1033 std::string contents;
1039 int64_t totalNumLines = 0;
1043 std::vector<std::unique_ptr<MLIRTextFileChunk>> chunks;
1047 MLIRTextFile::MLIRTextFile(
const lsp::URIForFile &uri, StringRef fileContents,
1049 std::vector<lsp::Diagnostic> &diagnostics)
1050 : context(registry,
MLIRContext::Threading::DISABLED),
1051 contents(fileContents.str()), version(version) {
1059 StringRef(contents).split(subContents,
"// -----");
1060 chunks.emplace_back(std::make_unique<MLIRTextFileChunk>(
1061 context, 0, uri, subContents.front(), diagnostics));
1063 uint64_t lineOffset = subContents.front().count(
'\n');
1064 for (StringRef docContents : llvm::drop_begin(subContents)) {
1065 unsigned currentNumDiags = diagnostics.size();
1066 auto chunk = std::make_unique<MLIRTextFileChunk>(context, lineOffset, uri,
1067 docContents, diagnostics);
1068 lineOffset += docContents.count(
'\n');
1073 llvm::drop_begin(diagnostics, currentNumDiags)) {
1074 chunk->adjustLocForChunkOffset(
diag.range);
1076 if (!
diag.relatedInformation)
1078 for (
auto &it : *
diag.relatedInformation)
1079 if (it.location.uri == uri)
1080 chunk->adjustLocForChunkOffset(it.location.range);
1082 chunks.emplace_back(std::move(chunk));
1084 totalNumLines = lineOffset;
1089 std::vector<lsp::Location> &locations) {
1090 MLIRTextFileChunk &chunk = getChunkFor(defPos);
1091 chunk.document.getLocationsOf(uri, defPos, locations);
1094 if (chunk.lineOffset == 0)
1098 chunk.adjustLocForChunkOffset(loc.range);
1103 std::vector<lsp::Location> &references) {
1104 MLIRTextFileChunk &chunk = getChunkFor(pos);
1105 chunk.document.findReferencesOf(uri, pos, references);
1108 if (chunk.lineOffset == 0)
1112 chunk.adjustLocForChunkOffset(loc.range);
1115 std::optional<lsp::Hover> MLIRTextFile::findHover(
const lsp::URIForFile &uri,
1117 MLIRTextFileChunk &chunk = getChunkFor(hoverPos);
1118 std::optional<lsp::Hover> hoverInfo = chunk.document.findHover(uri, hoverPos);
1121 if (chunk.lineOffset != 0 && hoverInfo && hoverInfo->range)
1122 chunk.adjustLocForChunkOffset(*hoverInfo->range);
1126 void MLIRTextFile::findDocumentSymbols(
1127 std::vector<lsp::DocumentSymbol> &symbols) {
1128 if (chunks.size() == 1)
1129 return chunks.front()->document.findDocumentSymbols(symbols);
1133 for (
unsigned i = 0, e = chunks.size(); i < e; ++i) {
1134 MLIRTextFileChunk &chunk = *chunks[i];
1137 : chunks[i + 1]->lineOffset);
1139 lsp::SymbolKind::Namespace,
1142 chunk.document.findDocumentSymbols(symbol.children);
1148 symbolsToFix.push_back(&childSymbol);
1150 while (!symbolsToFix.empty()) {
1152 chunk.adjustLocForChunkOffset(symbol->
range);
1156 symbolsToFix.push_back(&childSymbol);
1161 symbols.emplace_back(std::move(symbol));
1167 MLIRTextFileChunk &chunk = getChunkFor(completePos);
1174 chunk.adjustLocForChunkOffset(item.
textEdit->range);
1176 chunk.adjustLocForChunkOffset(edit.
range);
1178 return completionList;
1184 std::vector<lsp::CodeAction> &actions) {
1187 if (
diag.source !=
"mlir")
1190 MLIRTextFileChunk &chunk = getChunkFor(diagPos);
1194 action.
title =
"Add expected-* diagnostic checks";
1195 action.
kind = lsp::CodeAction::kQuickFix.str();
1198 switch (
diag.severity) {
1202 case lsp::DiagnosticSeverity::Warning:
1203 severity =
"warning";
1210 std::vector<lsp::TextEdit> edits;
1211 chunk.document.getCodeActionForDiagnostic(uri, diagPos, severity,
1212 diag.message, edits);
1215 if (
diag.relatedInformation) {
1216 for (
auto ¬eDiag : *
diag.relatedInformation) {
1217 if (noteDiag.location.uri != uri)
1219 diagPos = noteDiag.location.range.start;
1220 diagPos.
line -= chunk.lineOffset;
1221 chunk.document.getCodeActionForDiagnostic(uri, diagPos,
"note",
1222 noteDiag.message, edits);
1227 chunk.adjustLocForChunkOffset(edit.
range);
1229 action.
edit.emplace();
1230 action.
edit->changes[uri.
uri().str()] = std::move(edits);
1233 actions.emplace_back(std::move(action));
1238 MLIRTextFile::convertToBytecode() {
1240 if (chunks.size() != 1) {
1241 return llvm::make_error<lsp::LSPError>(
1242 "unexpected split file, please remove all `// -----`",
1243 lsp::ErrorCode::RequestFailed);
1245 return chunks.front()->document.convertToBytecode();
1248 MLIRTextFileChunk &MLIRTextFile::getChunkFor(
lsp::Position &pos) {
1249 if (chunks.size() == 1)
1250 return *chunks.front();
1254 auto it = llvm::upper_bound(
1255 chunks, pos, [](
const lsp::Position &pos,
const auto &chunk) {
1256 return static_cast<uint64_t
>(pos.
line) < chunk->lineOffset;
1258 MLIRTextFileChunk &chunk = it == chunks.end() ? *chunks.back() : **(--it);
1259 pos.
line -= chunk.lineOffset;
1275 llvm::StringMap<std::unique_ptr<MLIRTextFile>>
files;
1283 :
impl(std::make_unique<
Impl>(registry)) {}
1287 const URIForFile &uri, StringRef contents, int64_t version,
1288 std::vector<Diagnostic> &diagnostics) {
1289 impl->files[uri.
file()] = std::make_unique<MLIRTextFile>(
1290 uri, contents, version,
impl->registry, diagnostics);
1294 auto it =
impl->files.find(uri.
file());
1295 if (it ==
impl->files.end())
1296 return std::nullopt;
1298 int64_t version = it->second->getVersion();
1299 impl->files.erase(it);
1305 std::vector<Location> &locations) {
1306 auto fileIt =
impl->files.find(uri.
file());
1307 if (fileIt !=
impl->files.end())
1308 fileIt->second->getLocationsOf(uri, defPos, locations);
1313 std::vector<Location> &references) {
1314 auto fileIt =
impl->files.find(uri.
file());
1315 if (fileIt !=
impl->files.end())
1316 fileIt->second->findReferencesOf(uri, pos, references);
1321 auto fileIt =
impl->files.find(uri.
file());
1322 if (fileIt !=
impl->files.end())
1323 return fileIt->second->findHover(uri, hoverPos);
1324 return std::nullopt;
1328 const URIForFile &uri, std::vector<DocumentSymbol> &symbols) {
1329 auto fileIt =
impl->files.find(uri.
file());
1330 if (fileIt !=
impl->files.end())
1331 fileIt->second->findDocumentSymbols(symbols);
1337 auto fileIt =
impl->files.find(uri.
file());
1338 if (fileIt !=
impl->files.end())
1339 return fileIt->second->getCodeCompletion(uri, completePos);
1345 std::vector<CodeAction> &actions) {
1346 auto fileIt =
impl->files.find(uri.
file());
1347 if (fileIt !=
impl->files.end())
1348 fileIt->second->getCodeActions(uri, pos, context, actions);
1357 std::string errorMsg;
1367 &fallbackResourceMap);
1372 return llvm::make_error<lsp::LSPError>(
1373 "failed to parse bytecode source file: " + errorMsg,
1379 if (!llvm::hasSingleElement(parsedBlock)) {
1380 return llvm::make_error<lsp::LSPError>(
1381 "expected bytecode to contain a single top-level operation",
1394 nullptr, &fallbackResourceMap);
1396 llvm::raw_string_ostream os(result.
output);
1397 topOp->print(os, state);
1399 return std::move(result);
1404 auto fileIt =
impl->files.find(uri.
file());
1405 if (fileIt ==
impl->files.end()) {
1406 return llvm::make_error<lsp::LSPError>(
1407 "language server does not contain an entry for this source file",
1410 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 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.
Location getLoc()
The source location the operation was defined or derived from.
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()
unsigned getNumResults()
Return the number of results held by this operation.
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.
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.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
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.
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.