27 #include "llvm/ADT/IntervalMap.h"
28 #include "llvm/ADT/StringMap.h"
29 #include "llvm/ADT/StringSet.h"
30 #include "llvm/ADT/TypeSwitch.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/LSP/Logging.h"
33 #include "llvm/Support/Path.h"
41 static llvm::lsp::URIForFile
43 const llvm::lsp::URIForFile &mainFileURI) {
44 int bufferId = mgr.FindBufferContainingLoc(loc.Start);
45 if (bufferId == 0 || bufferId ==
static_cast<int>(mgr.getMainFileID()))
48 llvm::lsp::URIForFile::fromFile(
49 mgr.getBufferInfo(bufferId).Buffer->getBufferIdentifier());
52 llvm::lsp::Logger::error(
"Failed to create URI for include file: {0}",
60 return mgr.FindBufferContainingLoc(loc.Start) == mgr.getMainFileID();
64 static llvm::lsp::Location
66 const llvm::lsp::URIForFile &uri) {
68 llvm::lsp::Range(mgr, range));
72 static std::optional<llvm::lsp::Diagnostic>
74 const llvm::lsp::URIForFile &uri) {
75 llvm::lsp::Diagnostic lspDiag;
76 lspDiag.source =
"pdll";
80 lspDiag.category =
"Parse Error";
83 llvm::lsp::Location loc =
85 lspDiag.range = loc.range;
92 switch (
diag.getSeverity()) {
93 case ast::Diagnostic::Severity::DK_Note:
94 llvm_unreachable(
"expected notes to be handled separately");
95 case ast::Diagnostic::Severity::DK_Warning:
96 lspDiag.severity = llvm::lsp::DiagnosticSeverity::Warning;
98 case ast::Diagnostic::Severity::DK_Error:
101 case ast::Diagnostic::Severity::DK_Remark:
102 lspDiag.severity = llvm::lsp::DiagnosticSeverity::Information;
105 lspDiag.message =
diag.getMessage().str();
108 std::vector<llvm::lsp::DiagnosticRelatedInformation> relatedDiags;
110 relatedDiags.emplace_back(
112 note.getMessage().str());
114 if (!relatedDiags.empty())
115 lspDiag.relatedInformation = std::move(relatedDiags);
121 static std::optional<std::string>
137 struct PDLIndexSymbol {
138 explicit PDLIndexSymbol(
const ast::Decl *definition)
139 : definition(definition) {}
141 : definition(definition) {}
144 SMRange getDefLoc()
const {
146 llvm::dyn_cast_if_present<const ast::Decl *>(definition)) {
148 return declName ? declName->
getLoc() : decl->getLoc();
150 return cast<const ods::Operation *>(definition)->getLoc();
156 std::vector<SMRange> references;
163 PDLIndex() : intervalMap(allocator) {}
171 const PDLIndexSymbol *lookup(SMLoc loc,
172 SMRange *overlappedRange =
nullptr)
const;
178 llvm::IntervalMap<
const char *,
const PDLIndexSymbol *,
179 llvm::IntervalMapImpl::NodeSizer<
180 const char *,
const PDLIndexSymbol *>::LeafSize,
181 llvm::IntervalMapHalfOpenInfo<const char *>>;
184 MapT::Allocator allocator;
195 void PDLIndex::initialize(
const ast::Module &module,
197 auto getOrInsertDef = [&](
const auto *def) -> PDLIndexSymbol * {
198 auto it = defToSymbol.try_emplace(def,
nullptr);
200 it.first->second = std::make_unique<PDLIndexSymbol>(def);
201 return &*it.first->second;
203 auto insertDeclRef = [&](PDLIndexSymbol *sym, SMRange refLoc,
204 bool isDef =
false) {
205 const char *startLoc = refLoc.Start.getPointer();
206 const char *endLoc = refLoc.End.getPointer();
207 if (!intervalMap.overlaps(startLoc, endLoc)) {
208 intervalMap.insert(startLoc, endLoc, sym);
210 sym->references.push_back(refLoc);
213 auto insertODSOpRef = [&](StringRef opName, SMRange refLoc) {
218 PDLIndexSymbol *symbol = getOrInsertDef(odsOp);
219 insertDeclRef(symbol, odsOp->
getLoc(),
true);
220 insertDeclRef(symbol, refLoc);
225 if (
const auto *decl = dyn_cast<ast::OpNameDecl>(node)) {
226 if (std::optional<StringRef> name = decl->getName())
227 insertODSOpRef(*name, decl->getLoc());
228 }
else if (
const ast::Decl *decl = dyn_cast<ast::Decl>(node)) {
232 PDLIndexSymbol *declSym = getOrInsertDef(decl);
233 insertDeclRef(declSym, name->
getLoc(),
true);
235 if (
const auto *varDecl = dyn_cast<ast::VariableDecl>(decl)) {
237 for (
const auto &it : varDecl->getConstraints())
238 insertDeclRef(getOrInsertDef(it.constraint), it.referenceLoc);
240 }
else if (
const auto *expr = dyn_cast<ast::DeclRefExpr>(node)) {
241 insertDeclRef(getOrInsertDef(expr->getDecl()), expr->getLoc());
246 const PDLIndexSymbol *PDLIndex::lookup(SMLoc loc,
247 SMRange *overlappedRange)
const {
248 auto it = intervalMap.find(loc.getPointer());
249 if (!it.valid() || loc.getPointer() < it.start())
252 if (overlappedRange) {
253 *overlappedRange = SMRange(SMLoc::getFromPointer(it.start()),
254 SMLoc::getFromPointer(it.stop()));
267 PDLDocument(
const llvm::lsp::URIForFile &uri, StringRef contents,
268 const std::vector<std::string> &extraDirs,
269 std::vector<llvm::lsp::Diagnostic> &diagnostics);
270 PDLDocument(
const PDLDocument &) =
delete;
271 PDLDocument &operator=(
const PDLDocument &) =
delete;
277 void getLocationsOf(
const llvm::lsp::URIForFile &uri,
278 const llvm::lsp::Position &defPos,
279 std::vector<llvm::lsp::Location> &locations);
280 void findReferencesOf(
const llvm::lsp::URIForFile &uri,
281 const llvm::lsp::Position &pos,
282 std::vector<llvm::lsp::Location> &references);
288 void getDocumentLinks(
const llvm::lsp::URIForFile &uri,
289 std::vector<llvm::lsp::DocumentLink> &links);
295 std::optional<llvm::lsp::Hover>
296 findHover(
const llvm::lsp::URIForFile &uri,
297 const llvm::lsp::Position &hoverPos);
298 std::optional<llvm::lsp::Hover> findHover(
const ast::Decl *decl,
299 const SMRange &hoverRange);
301 const SMRange &hoverRange);
303 const SMRange &hoverRange);
305 const SMRange &hoverRange);
308 const SMRange &hoverRange);
309 template <
typename T>
311 buildHoverForUserConstraintOrRewrite(StringRef typeName,
const T *decl,
312 const SMRange &hoverRange);
318 void findDocumentSymbols(std::vector<llvm::lsp::DocumentSymbol> &symbols);
324 llvm::lsp::CompletionList
325 getCodeCompletion(
const llvm::lsp::URIForFile &uri,
326 const llvm::lsp::Position &completePos);
332 llvm::lsp::SignatureHelp getSignatureHelp(
const llvm::lsp::URIForFile &uri,
333 const llvm::lsp::Position &helpPos);
339 void getInlayHints(
const llvm::lsp::URIForFile &uri,
340 const llvm::lsp::Range &range,
341 std::vector<llvm::lsp::InlayHint> &inlayHints);
343 const llvm::lsp::URIForFile &uri,
344 std::vector<llvm::lsp::InlayHint> &inlayHints);
346 const llvm::lsp::URIForFile &uri,
347 std::vector<llvm::lsp::InlayHint> &inlayHints);
349 const llvm::lsp::URIForFile &uri,
350 std::vector<llvm::lsp::InlayHint> &inlayHints);
353 void addParameterHintFor(std::vector<llvm::lsp::InlayHint> &inlayHints,
367 std::vector<std::string> includeDirs;
370 llvm::SourceMgr sourceMgr;
377 FailureOr<ast::Module *> astModule;
387 PDLDocument::PDLDocument(
const llvm::lsp::URIForFile &uri, StringRef contents,
388 const std::vector<std::string> &extraDirs,
389 std::vector<llvm::lsp::Diagnostic> &diagnostics)
390 : astContext(odsContext) {
391 auto memBuffer = llvm::MemoryBuffer::getMemBufferCopy(contents, uri.file());
393 llvm::lsp::Logger::error(
"Failed to create memory buffer for file",
400 llvm::sys::path::remove_filename(uriDirectory);
401 includeDirs.push_back(uriDirectory.str().str());
402 llvm::append_range(includeDirs, extraDirs);
404 sourceMgr.setIncludeDirs(includeDirs);
405 sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
409 diagnostics.push_back(std::move(*lspDiag));
421 index.initialize(**astModule, odsContext);
428 void PDLDocument::getLocationsOf(
const llvm::lsp::URIForFile &uri,
429 const llvm::lsp::Position &defPos,
430 std::vector<llvm::lsp::Location> &locations) {
431 SMLoc posLoc = defPos.getAsSMLoc(sourceMgr);
432 const PDLIndexSymbol *symbol = index.lookup(posLoc);
439 void PDLDocument::findReferencesOf(
440 const llvm::lsp::URIForFile &uri,
const llvm::lsp::Position &pos,
441 std::vector<llvm::lsp::Location> &references) {
442 SMLoc posLoc = pos.getAsSMLoc(sourceMgr);
443 const PDLIndexSymbol *symbol = index.lookup(posLoc);
448 for (SMRange refLoc : symbol->references)
456 void PDLDocument::getDocumentLinks(
457 const llvm::lsp::URIForFile &uri,
458 std::vector<llvm::lsp::DocumentLink> &links) {
460 links.emplace_back(include.range, include.uri);
467 std::optional<llvm::lsp::Hover>
468 PDLDocument::findHover(
const llvm::lsp::URIForFile &uri,
469 const llvm::lsp::Position &hoverPos) {
470 SMLoc posLoc = hoverPos.getAsSMLoc(sourceMgr);
474 if (include.range.contains(hoverPos))
475 return include.buildHover();
479 const PDLIndexSymbol *symbol = index.lookup(posLoc, &hoverRange);
485 llvm::dyn_cast_if_present<const ods::Operation *>(symbol->definition))
486 return buildHoverForOpName(op, hoverRange);
487 const auto *decl = cast<const ast::Decl *>(symbol->definition);
488 return findHover(decl, hoverRange);
491 std::optional<llvm::lsp::Hover>
492 PDLDocument::findHover(
const ast::Decl *decl,
const SMRange &hoverRange) {
494 if (
const auto *varDecl = dyn_cast<ast::VariableDecl>(decl))
495 return buildHoverForVariable(varDecl, hoverRange);
498 if (
const auto *patternDecl = dyn_cast<ast::PatternDecl>(decl))
499 return buildHoverForPattern(patternDecl, hoverRange);
502 if (
const auto *cst = dyn_cast<ast::CoreConstraintDecl>(decl))
503 return buildHoverForCoreConstraint(cst, hoverRange);
506 if (
const auto *cst = dyn_cast<ast::UserConstraintDecl>(decl))
507 return buildHoverForUserConstraintOrRewrite(
"Constraint", cst, hoverRange);
510 if (
const auto *
rewrite = dyn_cast<ast::UserRewriteDecl>(decl))
511 return buildHoverForUserConstraintOrRewrite(
"Rewrite",
rewrite, hoverRange);
516 llvm::lsp::Hover PDLDocument::buildHoverForOpName(
const ods::Operation *op,
517 const SMRange &hoverRange) {
518 llvm::lsp::Hover hover(llvm::lsp::Range(sourceMgr, hoverRange));
520 llvm::raw_string_ostream hoverOS(hover.contents.value);
521 hoverOS <<
"**OpName**: `" << op->
getName() <<
"`\n***\n"
530 const SMRange &hoverRange) {
531 llvm::lsp::Hover hover(llvm::lsp::Range(sourceMgr, hoverRange));
533 llvm::raw_string_ostream hoverOS(hover.contents.value);
534 hoverOS <<
"**Variable**: `" << varDecl->
getName().
getName() <<
"`\n***\n"
535 <<
"Type: `" << varDecl->
getType() <<
"`\n";
540 llvm::lsp::Hover PDLDocument::buildHoverForPattern(
const ast::PatternDecl *decl,
541 const SMRange &hoverRange) {
542 llvm::lsp::Hover hover(llvm::lsp::Range(sourceMgr, hoverRange));
544 llvm::raw_string_ostream hoverOS(hover.contents.value);
545 hoverOS <<
"**Pattern**";
546 if (
const ast::Name *name = decl->getName())
547 hoverOS <<
": `" << name->
getName() <<
"`";
548 hoverOS <<
"\n***\n";
549 if (std::optional<uint16_t> benefit = decl->
getBenefit())
550 hoverOS <<
"Benefit: " << *benefit <<
"\n";
552 hoverOS <<
"HasBoundedRewriteRecursion\n";
553 hoverOS <<
"RootOp: `"
558 hoverOS <<
"\n" << *doc <<
"\n";
565 const SMRange &hoverRange) {
566 llvm::lsp::Hover hover(llvm::lsp::Range(sourceMgr, hoverRange));
568 llvm::raw_string_ostream hoverOS(hover.contents.value);
569 hoverOS <<
"**Constraint**: `";
574 if (std::optional<StringRef> name = opCst->
getName())
575 hoverOS <<
"<" << *name <<
">";
579 hoverOS <<
"TypeRange";
583 hoverOS <<
"ValueRange";
590 template <
typename T>
591 llvm::lsp::Hover PDLDocument::buildHoverForUserConstraintOrRewrite(
592 StringRef typeName,
const T *decl,
const SMRange &hoverRange) {
593 llvm::lsp::Hover hover(llvm::lsp::Range(sourceMgr, hoverRange));
595 llvm::raw_string_ostream hoverOS(hover.contents.value);
596 hoverOS <<
"**" << typeName <<
"**: `" << decl->getName().getName()
599 if (!inputs.empty()) {
600 hoverOS <<
"Parameters:\n";
602 hoverOS <<
"* " << input->getName().getName() <<
": `"
603 << input->getType() <<
"`\n";
606 ast::Type resultType = decl->getResultType();
607 if (
auto resultTupleTy = dyn_cast<ast::TupleType>(resultType)) {
608 if (!resultTupleTy.empty()) {
609 hoverOS <<
"Results:\n";
610 for (
auto it : llvm::zip(resultTupleTy.getElementNames(),
611 resultTupleTy.getElementTypes())) {
612 StringRef name = std::get<0>(it);
613 hoverOS <<
"* " << (name.empty() ?
"" : (name +
": ")) <<
"`"
614 << std::get<1>(it) <<
"`\n";
619 hoverOS <<
"Results:\n* `" << resultType <<
"`\n";
625 hoverOS <<
"\n" << *doc <<
"\n";
634 void PDLDocument::findDocumentSymbols(
635 std::vector<llvm::lsp::DocumentSymbol> &symbols) {
639 for (
const ast::Decl *decl : (*astModule)->getChildren()) {
643 if (
const auto *patternDecl = dyn_cast<ast::PatternDecl>(decl)) {
646 SMRange nameLoc = name ? name->
getLoc() : patternDecl->getLoc();
647 SMRange bodyLoc(nameLoc.Start, patternDecl->getBody()->getLoc().End);
649 symbols.emplace_back(name ? name->
getName() :
"<pattern>",
650 llvm::lsp::SymbolKind::Class,
651 llvm::lsp::Range(sourceMgr, bodyLoc),
652 llvm::lsp::Range(sourceMgr, nameLoc));
653 }
else if (
const auto *cDecl = dyn_cast<ast::UserConstraintDecl>(decl)) {
655 SMRange nameLoc = cDecl->getName().getLoc();
656 SMRange bodyLoc = nameLoc;
658 symbols.emplace_back(cDecl->getName().getName(),
659 llvm::lsp::SymbolKind::Function,
660 llvm::lsp::Range(sourceMgr, bodyLoc),
661 llvm::lsp::Range(sourceMgr, nameLoc));
662 }
else if (
const auto *cDecl = dyn_cast<ast::UserRewriteDecl>(decl)) {
664 SMRange nameLoc = cDecl->getName().getLoc();
665 SMRange bodyLoc = nameLoc;
667 symbols.emplace_back(cDecl->getName().getName(),
668 llvm::lsp::SymbolKind::Function,
669 llvm::lsp::Range(sourceMgr, bodyLoc),
670 llvm::lsp::Range(sourceMgr, nameLoc));
682 LSPCodeCompleteContext(SMLoc completeLoc, llvm::SourceMgr &sourceMgr,
683 llvm::lsp::CompletionList &completionList,
687 completionList(completionList), odsContext(odsContext),
688 includeDirs(includeDirs) {}
693 for (
unsigned i = 0, e = tupleType.size(); i < e; ++i) {
695 llvm::lsp::CompletionItem item;
696 item.label = llvm::formatv(
"{0} (field #{0})", i).str();
697 item.insertText = Twine(i).str();
698 item.filterText = item.sortText = item.insertText;
699 item.kind = llvm::lsp::CompletionItemKind::Field;
700 item.detail = llvm::formatv(
"{0}: {1}", i, elementTypes[i]);
701 item.insertTextFormat = llvm::lsp::InsertTextFormat::PlainText;
702 completionList.items.emplace_back(item);
705 if (!elementNames[i].empty()) {
707 llvm::formatv(
"{1} (field #{0})", i, elementNames[i]).str();
708 item.filterText = item.label;
709 item.insertText = elementNames[i].str();
710 completionList.items.emplace_back(item);
726 llvm::lsp::CompletionItem item;
727 item.label = llvm::formatv(
"{0} (field #{0})", it.index()).str();
728 item.insertText = Twine(it.index()).str();
729 item.filterText = item.sortText = item.insertText;
730 item.kind = llvm::lsp::CompletionItemKind::Field;
733 item.detail = llvm::formatv(
"{0}: Value", it.index()).str();
736 item.detail = llvm::formatv(
"{0}: Value?", it.index()).str();
739 item.detail = llvm::formatv(
"{0}: ValueRange", it.index()).str();
742 item.documentation = llvm::lsp::MarkupContent{
743 llvm::lsp::MarkupKind::Markdown,
744 llvm::formatv(
"{0}\n\n```c++\n{1}\n```\n", constraint.
getSummary(),
747 item.insertTextFormat = llvm::lsp::InsertTextFormat::PlainText;
748 completionList.items.emplace_back(item);
752 if (!result.
getName().empty()) {
754 llvm::formatv(
"{1} (field #{0})", it.index(), result.
getName())
756 item.filterText = item.label;
757 item.insertText = result.
getName().str();
758 completionList.items.emplace_back(item);
771 llvm::lsp::CompletionItem item;
772 item.label = attr.
getName().str();
773 item.kind = llvm::lsp::CompletionItemKind::Field;
774 item.detail = attr.isOptional() ?
"optional" :
"";
775 item.documentation = llvm::lsp::MarkupContent{
776 llvm::lsp::MarkupKind::Markdown,
777 llvm::formatv(
"{0}\n\n```c++\n{1}\n```\n", constraint.
getSummary(),
780 item.insertTextFormat = llvm::lsp::InsertTextFormat::PlainText;
781 completionList.items.emplace_back(item);
786 bool allowInlineTypeConstraints,
788 auto addCoreConstraint = [&](StringRef constraint, StringRef mlirType,
789 StringRef snippetText =
"") {
790 llvm::lsp::CompletionItem item;
791 item.label = constraint.str();
792 item.kind = llvm::lsp::CompletionItemKind::Class;
793 item.detail = (constraint +
" constraint").str();
794 item.documentation = llvm::lsp::MarkupContent{
795 llvm::lsp::MarkupKind::Markdown,
796 (
"A single entity core constraint of type `" + mlirType +
"`").str()};
798 item.insertText = snippetText.str();
799 item.insertTextFormat = snippetText.empty()
800 ? llvm::lsp::InsertTextFormat::PlainText
801 : llvm::lsp::InsertTextFormat::Snippet;
802 completionList.items.emplace_back(item);
809 addCoreConstraint(
"Attr",
"mlir::Attribute");
810 addCoreConstraint(
"Op",
"mlir::Operation *");
811 addCoreConstraint(
"Value",
"mlir::Value");
812 addCoreConstraint(
"ValueRange",
"mlir::ValueRange");
813 addCoreConstraint(
"Type",
"mlir::Type");
814 addCoreConstraint(
"TypeRange",
"mlir::TypeRange");
816 if (allowInlineTypeConstraints) {
818 if (!currentType || isa<ast::AttributeType>(currentType))
819 addCoreConstraint(
"Attr<type>",
"mlir::Attribute",
"Attr<$1>");
821 if (!currentType || isa<ast::ValueType>(currentType))
822 addCoreConstraint(
"Value<type>",
"mlir::Value",
"Value<$1>");
824 if (!currentType || isa<ast::ValueRangeType>(currentType))
825 addCoreConstraint(
"ValueRange<type>",
"mlir::ValueRange",
831 for (
const ast::Decl *decl : scope->getDecls()) {
832 if (
const auto *cst = dyn_cast<ast::UserConstraintDecl>(decl)) {
833 llvm::lsp::CompletionItem item;
834 item.label = cst->getName().getName().str();
835 item.kind = llvm::lsp::CompletionItemKind::Interface;
836 item.sortText =
"2_" + item.label;
840 if (cst->getInputs().size() != 1)
844 ast::Type constraintType = cst->getInputs()[0]->getType();
845 if (currentType && !currentType.refineWith(constraintType))
850 llvm::raw_string_ostream strOS(item.detail);
852 llvm::interleaveComma(
854 strOS << var->getName().getName() <<
": " << var->getType();
856 strOS <<
") -> " << cst->getResultType();
860 if (std::optional<std::string> doc =
862 item.documentation = llvm::lsp::MarkupContent{
863 llvm::lsp::MarkupKind::Markdown, std::move(*doc)};
866 completionList.items.emplace_back(item);
870 scope = scope->getParentScope();
877 llvm::lsp::CompletionItem item;
878 item.label = dialect.getName().str();
879 item.kind = llvm::lsp::CompletionItemKind::Class;
880 item.insertTextFormat = llvm::lsp::InsertTextFormat::PlainText;
881 completionList.items.emplace_back(item);
893 llvm::lsp::CompletionItem item;
894 item.label = op.
getName().drop_front(dialectName.size() + 1).str();
895 item.kind = llvm::lsp::CompletionItemKind::Field;
896 item.insertTextFormat = llvm::lsp::InsertTextFormat::PlainText;
897 completionList.items.emplace_back(item);
902 auto addSimpleConstraint = [&](StringRef constraint, StringRef desc,
903 StringRef snippetText =
"") {
904 llvm::lsp::CompletionItem item;
905 item.label = constraint.str();
906 item.kind = llvm::lsp::CompletionItemKind::Class;
907 item.detail =
"pattern metadata";
909 llvm::lsp::MarkupContent{llvm::lsp::MarkupKind::Markdown, desc.str()};
910 item.insertText = snippetText.str();
911 item.insertTextFormat = snippetText.empty()
912 ? llvm::lsp::InsertTextFormat::PlainText
913 : llvm::lsp::InsertTextFormat::Snippet;
914 completionList.items.emplace_back(item);
917 addSimpleConstraint(
"benefit",
"The `benefit` of matching the pattern.",
919 addSimpleConstraint(
"recursion",
920 "The pattern properly handles recursive application.");
927 llvm::sys::path::native(nativeRelDir);
933 auto addIncludeCompletion = [&](StringRef path,
bool isDirectory) {
934 llvm::lsp::CompletionItem item;
935 item.label = path.str();
936 item.kind = isDirectory ? llvm::lsp::CompletionItemKind::Folder
937 : llvm::lsp::CompletionItemKind::File;
938 if (seenResults.insert(item.label).second)
939 completionList.items.emplace_back(item);
944 for (StringRef includeDir : includeDirs) {
946 if (!nativeRelDir.empty())
947 llvm::sys::path::append(dir, nativeRelDir);
949 std::error_code errorCode;
950 for (
auto it = llvm::sys::fs::directory_iterator(dir, errorCode),
951 e = llvm::sys::fs::directory_iterator();
952 !errorCode && it != e; it.increment(errorCode)) {
953 StringRef filename = llvm::sys::path::filename(it->path());
958 llvm::sys::fs::file_type fileType = it->type();
959 if (fileType == llvm::sys::fs::file_type::symlink_file) {
960 if (
auto fileStatus = it->status())
961 fileType = fileStatus->type();
965 case llvm::sys::fs::file_type::directory_file:
966 addIncludeCompletion(filename,
true);
968 case llvm::sys::fs::file_type::regular_file: {
970 if (filename.ends_with(
".pdll") || filename.ends_with(
".td"))
971 addIncludeCompletion(filename,
false);
982 llvm::sort(completionList.items, [](
const llvm::lsp::CompletionItem &lhs,
983 const llvm::lsp::CompletionItem &rhs) {
984 return lhs.label < rhs.label;
989 llvm::SourceMgr &sourceMgr;
990 llvm::lsp::CompletionList &completionList;
996 llvm::lsp::CompletionList
997 PDLDocument::getCodeCompletion(
const llvm::lsp::URIForFile &uri,
998 const llvm::lsp::Position &completePos) {
999 SMLoc posLoc = completePos.getAsSMLoc(sourceMgr);
1000 if (!posLoc.isValid())
1001 return llvm::lsp::CompletionList();
1006 llvm::lsp::CompletionList completionList;
1007 LSPCodeCompleteContext lspCompleteContext(posLoc, sourceMgr, completionList,
1009 sourceMgr.getIncludeDirs());
1013 &lspCompleteContext);
1015 return completionList;
1025 LSPSignatureHelpContext(SMLoc completeLoc, llvm::SourceMgr &sourceMgr,
1026 llvm::lsp::SignatureHelp &signatureHelp,
1029 signatureHelp(signatureHelp), odsContext(odsContext) {}
1032 unsigned currentNumArgs)
final {
1033 signatureHelp.activeParameter = currentNumArgs;
1035 llvm::lsp::SignatureInformation signatureInfo;
1037 llvm::raw_string_ostream strOS(signatureInfo.label);
1038 strOS << callable->getName()->getName() <<
"(";
1040 unsigned paramStart = strOS.str().size();
1041 strOS << var->getName().getName() <<
": " << var->getType();
1042 unsigned paramEnd = strOS.str().size();
1043 signatureInfo.parameters.emplace_back(llvm::lsp::ParameterInformation{
1044 StringRef(strOS.str()).slice(paramStart, paramEnd).str(),
1045 std::make_pair(paramStart, paramEnd), std::string()});
1047 llvm::interleaveComma(callable->getInputs(), strOS, formatParamFn);
1048 strOS <<
") -> " << callable->getResultType();
1052 if (std::optional<std::string> doc =
1054 signatureInfo.documentation = std::move(*doc);
1056 signatureHelp.signatures.emplace_back(std::move(signatureInfo));
1061 unsigned currentNumOperands)
final {
1064 codeCompleteOperationOperandOrResultSignature(
1067 currentNumOperands,
"operand",
"Value");
1071 unsigned currentNumResults)
final {
1074 codeCompleteOperationOperandOrResultSignature(
1077 currentNumResults,
"result",
"Type");
1080 void codeCompleteOperationOperandOrResultSignature(
1083 StringRef label, StringRef dataType) {
1084 signatureHelp.activeParameter = currentValue;
1090 if (odsOp && currentValue < values.size()) {
1091 llvm::lsp::SignatureInformation signatureInfo;
1095 llvm::raw_string_ostream strOS(signatureInfo.label);
1098 unsigned paramStart = strOS.str().size();
1100 strOS << value.getName() <<
": ";
1102 StringRef constraintDoc = value.getConstraint().getSummary();
1103 std::string paramDoc;
1104 switch (value.getVariableLengthKind()) {
1107 paramDoc = constraintDoc.str();
1110 strOS << dataType <<
"?";
1111 paramDoc = (
"optional: " + constraintDoc).str();
1114 strOS << dataType <<
"Range";
1115 paramDoc = (
"variadic: " + constraintDoc).str();
1119 unsigned paramEnd = strOS.str().size();
1120 signatureInfo.parameters.emplace_back(llvm::lsp::ParameterInformation{
1121 StringRef(strOS.str()).slice(paramStart, paramEnd).str(),
1122 std::make_pair(paramStart, paramEnd), paramDoc});
1124 llvm::interleaveComma(values, strOS, formatFn);
1127 signatureInfo.documentation =
1128 llvm::formatv(
"`op<{0}>` ODS {1} specification", *opName, label)
1130 signatureHelp.signatures.emplace_back(std::move(signatureInfo));
1134 if (currentValue == 0 && (!odsOp || !values.empty())) {
1135 llvm::lsp::SignatureInformation signatureInfo;
1136 signatureInfo.label =
1137 llvm::formatv(
"(<{0}s>: {1}Range)", label, dataType).str();
1138 signatureInfo.documentation =
1139 (
"Generic operation " + label +
" specification").str();
1140 signatureInfo.parameters.emplace_back(llvm::lsp::ParameterInformation{
1141 StringRef(signatureInfo.label).drop_front().drop_back().str(),
1142 std::pair<unsigned, unsigned>(1, signatureInfo.label.size() - 1),
1143 (
"All of the " + label +
"s of the operation.").str()});
1144 signatureHelp.signatures.emplace_back(std::move(signatureInfo));
1149 llvm::SourceMgr &sourceMgr;
1150 llvm::lsp::SignatureHelp &signatureHelp;
1155 llvm::lsp::SignatureHelp
1156 PDLDocument::getSignatureHelp(
const llvm::lsp::URIForFile &uri,
1157 const llvm::lsp::Position &helpPos) {
1158 SMLoc posLoc = helpPos.getAsSMLoc(sourceMgr);
1159 if (!posLoc.isValid())
1160 return llvm::lsp::SignatureHelp();
1165 llvm::lsp::SignatureHelp signatureHelp;
1166 LSPSignatureHelpContext completeContext(posLoc, sourceMgr, signatureHelp,
1173 return signatureHelp;
1186 if (
auto *ref = dyn_cast<ast::DeclRefExpr>(expr)) {
1188 if (declName && declName->
getName() == name)
1195 void PDLDocument::getInlayHints(
const llvm::lsp::URIForFile &uri,
1196 const llvm::lsp::Range &range,
1197 std::vector<llvm::lsp::InlayHint> &inlayHints) {
1200 SMRange rangeLoc = range.getAsSMRange(sourceMgr);
1201 if (!rangeLoc.isValid())
1203 (*astModule)->walk([&](
const ast::Node *node) {
1204 SMRange loc = node->
getLoc();
1214 [&](
const auto *node) {
1215 this->getInlayHintsFor(node, uri, inlayHints);
1220 void PDLDocument::getInlayHintsFor(
1222 std::vector<llvm::lsp::InlayHint> &inlayHints) {
1233 if (isa<ast::OperationExpr>(expr))
1237 llvm::lsp::InlayHint hint(llvm::lsp::InlayHintKind::Type,
1238 llvm::lsp::Position(sourceMgr, decl->getLoc().End));
1240 llvm::raw_string_ostream labelOS(hint.label);
1241 labelOS <<
": " << decl->
getType();
1244 inlayHints.emplace_back(std::move(hint));
1247 void PDLDocument::getInlayHintsFor(
1248 const ast::CallExpr *expr,
const llvm::lsp::URIForFile &uri,
1249 std::vector<llvm::lsp::InlayHint> &inlayHints) {
1251 const auto *callableRef = dyn_cast<ast::DeclRefExpr>(expr->
getCallableExpr());
1252 const auto *callable =
1253 callableRef ? dyn_cast<ast::CallableDecl>(callableRef->getDecl())
1259 for (
const auto &it : llvm::zip(expr->
getArguments(), callable->getInputs()))
1260 addParameterHintFor(inlayHints, std::get<0>(it),
1261 std::get<1>(it)->getName().getName());
1264 void PDLDocument::getInlayHintsFor(
1266 std::vector<llvm::lsp::InlayHint> &inlayHints) {
1271 auto addOpHint = [&](
const ast::Expr *valueExpr, StringRef label) {
1274 if (expr->getLoc().Start == valueExpr->
getLoc().Start)
1276 addParameterHintFor(inlayHints, valueExpr, label);
1284 StringRef allValuesName) {
1290 if (values.size() != odsValues.size()) {
1292 if (values.size() == 1)
1293 return addOpHint(values.front(), allValuesName);
1297 for (
const auto &it : llvm::zip(values, odsValues))
1298 addOpHint(std::get<0>(it), std::get<1>(it).getName());
1312 void PDLDocument::addParameterHintFor(
1313 std::vector<llvm::lsp::InlayHint> &inlayHints,
const ast::Expr *expr,
1318 llvm::lsp::InlayHint hint(
1319 llvm::lsp::InlayHintKind::Parameter,
1320 llvm::lsp::Position(sourceMgr, expr->
getLoc().Start));
1321 hint.label = (label +
":").str();
1322 hint.paddingRight =
true;
1323 inlayHints.emplace_back(std::move(hint));
1330 void PDLDocument::getPDLLViewOutput(raw_ostream &os,
1334 if (
kind == lsp::PDLLViewOutputKind::AST) {
1335 (*astModule)->print(os);
1348 if (
kind == lsp::PDLLViewOutputKind::MLIR) {
1354 assert(
kind == lsp::PDLLViewOutputKind::CPP &&
1355 "unexpected PDLLViewOutputKind");
1365 struct PDLTextFileChunk {
1366 PDLTextFileChunk(uint64_t lineOffset,
const llvm::lsp::URIForFile &uri,
1368 const std::vector<std::string> &extraDirs,
1369 std::vector<llvm::lsp::Diagnostic> &diagnostics)
1370 : lineOffset(lineOffset),
1371 document(uri, contents, extraDirs, diagnostics) {}
1375 void adjustLocForChunkOffset(llvm::lsp::Range &range) {
1376 adjustLocForChunkOffset(range.start);
1377 adjustLocForChunkOffset(range.end);
1381 void adjustLocForChunkOffset(llvm::lsp::Position &pos) {
1382 pos.line += lineOffset;
1386 uint64_t lineOffset;
1388 PDLDocument document;
1400 PDLTextFile(
const llvm::lsp::URIForFile &uri, StringRef fileContents,
1401 int64_t version,
const std::vector<std::string> &extraDirs,
1402 std::vector<llvm::lsp::Diagnostic> &diagnostics);
1405 int64_t getVersion()
const {
return version; }
1410 update(
const llvm::lsp::URIForFile &uri, int64_t newVersion,
1412 std::vector<llvm::lsp::Diagnostic> &diagnostics);
1418 void getLocationsOf(
const llvm::lsp::URIForFile &uri,
1419 llvm::lsp::Position defPos,
1420 std::vector<llvm::lsp::Location> &locations);
1421 void findReferencesOf(
const llvm::lsp::URIForFile &uri,
1422 llvm::lsp::Position pos,
1423 std::vector<llvm::lsp::Location> &references);
1424 void getDocumentLinks(
const llvm::lsp::URIForFile &uri,
1425 std::vector<llvm::lsp::DocumentLink> &links);
1426 std::optional<llvm::lsp::Hover> findHover(
const llvm::lsp::URIForFile &uri,
1427 llvm::lsp::Position hoverPos);
1428 void findDocumentSymbols(std::vector<llvm::lsp::DocumentSymbol> &symbols);
1429 llvm::lsp::CompletionList getCodeCompletion(
const llvm::lsp::URIForFile &uri,
1430 llvm::lsp::Position completePos);
1431 llvm::lsp::SignatureHelp getSignatureHelp(
const llvm::lsp::URIForFile &uri,
1432 llvm::lsp::Position helpPos);
1433 void getInlayHints(
const llvm::lsp::URIForFile &uri, llvm::lsp::Range range,
1434 std::vector<llvm::lsp::InlayHint> &inlayHints);
1438 using ChunkIterator = llvm::pointee_iterator<
1439 std::vector<std::unique_ptr<PDLTextFileChunk>>::iterator>;
1442 void initialize(
const llvm::lsp::URIForFile &uri, int64_t newVersion,
1443 std::vector<llvm::lsp::Diagnostic> &diagnostics);
1448 ChunkIterator getChunkItFor(llvm::lsp::Position &pos);
1449 PDLTextFileChunk &getChunkFor(llvm::lsp::Position &pos) {
1450 return *getChunkItFor(pos);
1454 std::string contents;
1457 int64_t version = 0;
1460 int64_t totalNumLines = 0;
1464 std::vector<std::unique_ptr<PDLTextFileChunk>> chunks;
1467 std::vector<std::string> extraIncludeDirs;
1471 PDLTextFile::PDLTextFile(
const llvm::lsp::URIForFile &uri,
1472 StringRef fileContents, int64_t version,
1473 const std::vector<std::string> &extraDirs,
1474 std::vector<llvm::lsp::Diagnostic> &diagnostics)
1475 : contents(fileContents.str()), extraIncludeDirs(extraDirs) {
1476 initialize(uri, version, diagnostics);
1480 PDLTextFile::update(
const llvm::lsp::URIForFile &uri, int64_t newVersion,
1482 std::vector<llvm::lsp::Diagnostic> &diagnostics) {
1483 if (
failed(llvm::lsp::TextDocumentContentChangeEvent::applyTo(changes,
1485 llvm::lsp::Logger::error(
"Failed to update contents of {0}", uri.file());
1490 initialize(uri, newVersion, diagnostics);
1494 void PDLTextFile::getLocationsOf(
const llvm::lsp::URIForFile &uri,
1495 llvm::lsp::Position defPos,
1496 std::vector<llvm::lsp::Location> &locations) {
1497 PDLTextFileChunk &chunk = getChunkFor(defPos);
1498 chunk.document.getLocationsOf(uri, defPos, locations);
1501 if (chunk.lineOffset == 0)
1503 for (llvm::lsp::Location &loc : locations)
1505 chunk.adjustLocForChunkOffset(loc.range);
1508 void PDLTextFile::findReferencesOf(
1509 const llvm::lsp::URIForFile &uri, llvm::lsp::Position pos,
1510 std::vector<llvm::lsp::Location> &references) {
1511 PDLTextFileChunk &chunk = getChunkFor(pos);
1512 chunk.document.findReferencesOf(uri, pos, references);
1515 if (chunk.lineOffset == 0)
1517 for (llvm::lsp::Location &loc : references)
1519 chunk.adjustLocForChunkOffset(loc.range);
1522 void PDLTextFile::getDocumentLinks(
1523 const llvm::lsp::URIForFile &uri,
1524 std::vector<llvm::lsp::DocumentLink> &links) {
1525 chunks.front()->document.getDocumentLinks(uri, links);
1526 for (
const auto &it : llvm::drop_begin(chunks)) {
1527 size_t currentNumLinks = links.size();
1528 it->document.getDocumentLinks(uri, links);
1532 for (
auto &link : llvm::drop_begin(links, currentNumLinks))
1533 it->adjustLocForChunkOffset(link.range);
1537 std::optional<llvm::lsp::Hover>
1538 PDLTextFile::findHover(
const llvm::lsp::URIForFile &uri,
1539 llvm::lsp::Position hoverPos) {
1540 PDLTextFileChunk &chunk = getChunkFor(hoverPos);
1541 std::optional<llvm::lsp::Hover> hoverInfo =
1542 chunk.document.findHover(uri, hoverPos);
1545 if (chunk.lineOffset != 0 && hoverInfo && hoverInfo->range)
1546 chunk.adjustLocForChunkOffset(*hoverInfo->range);
1550 void PDLTextFile::findDocumentSymbols(
1551 std::vector<llvm::lsp::DocumentSymbol> &symbols) {
1552 if (chunks.size() == 1)
1553 return chunks.front()->document.findDocumentSymbols(symbols);
1557 for (
unsigned i = 0, e = chunks.size(); i < e; ++i) {
1558 PDLTextFileChunk &chunk = *chunks[i];
1559 llvm::lsp::Position startPos(chunk.lineOffset);
1560 llvm::lsp::Position endPos((i == e - 1) ? totalNumLines - 1
1561 : chunks[i + 1]->lineOffset);
1562 llvm::lsp::DocumentSymbol symbol(
1563 "<file-split-" + Twine(i) +
">", llvm::lsp::SymbolKind::Namespace,
1564 llvm::lsp::Range(startPos, endPos),
1565 llvm::lsp::Range(startPos));
1566 chunk.document.findDocumentSymbols(symbol.children);
1571 for (llvm::lsp::DocumentSymbol &childSymbol : symbol.children)
1572 symbolsToFix.push_back(&childSymbol);
1574 while (!symbolsToFix.empty()) {
1575 llvm::lsp::DocumentSymbol *symbol = symbolsToFix.pop_back_val();
1576 chunk.adjustLocForChunkOffset(symbol->range);
1577 chunk.adjustLocForChunkOffset(symbol->selectionRange);
1579 for (llvm::lsp::DocumentSymbol &childSymbol : symbol->children)
1580 symbolsToFix.push_back(&childSymbol);
1585 symbols.emplace_back(std::move(symbol));
1589 llvm::lsp::CompletionList
1590 PDLTextFile::getCodeCompletion(
const llvm::lsp::URIForFile &uri,
1591 llvm::lsp::Position completePos) {
1592 PDLTextFileChunk &chunk = getChunkFor(completePos);
1593 llvm::lsp::CompletionList completionList =
1594 chunk.document.getCodeCompletion(uri, completePos);
1597 for (llvm::lsp::CompletionItem &item : completionList.items) {
1599 chunk.adjustLocForChunkOffset(item.textEdit->range);
1600 for (llvm::lsp::TextEdit &edit : item.additionalTextEdits)
1601 chunk.adjustLocForChunkOffset(edit.range);
1603 return completionList;
1606 llvm::lsp::SignatureHelp
1607 PDLTextFile::getSignatureHelp(
const llvm::lsp::URIForFile &uri,
1608 llvm::lsp::Position helpPos) {
1609 return getChunkFor(helpPos).document.getSignatureHelp(uri, helpPos);
1612 void PDLTextFile::getInlayHints(
const llvm::lsp::URIForFile &uri,
1613 llvm::lsp::Range range,
1614 std::vector<llvm::lsp::InlayHint> &inlayHints) {
1615 auto startIt = getChunkItFor(range.start);
1616 auto endIt = getChunkItFor(range.end);
1619 auto getHintsForChunk = [&](ChunkIterator chunkIt, llvm::lsp::Range range) {
1620 size_t currentNumHints = inlayHints.size();
1621 chunkIt->document.getInlayHints(uri, range, inlayHints);
1625 if (&*chunkIt != &*chunks.front()) {
1626 for (
auto &hint : llvm::drop_begin(inlayHints, currentNumHints))
1627 chunkIt->adjustLocForChunkOffset(hint.position);
1631 auto getNumLines = [](ChunkIterator chunkIt) {
1632 return (chunkIt + 1)->lineOffset - chunkIt->lineOffset;
1636 if (startIt == endIt)
1637 return getHintsForChunk(startIt, range);
1641 getHintsForChunk(startIt,
1642 llvm::lsp::Range(range.start, getNumLines(startIt)));
1645 for (++startIt; startIt != endIt; ++startIt)
1646 getHintsForChunk(startIt, llvm::lsp::Range(0, getNumLines(startIt)));
1650 getHintsForChunk(startIt, llvm::lsp::Range(0, range.end));
1657 llvm::raw_string_ostream outputOS(result.
output);
1659 llvm::make_pointee_range(chunks),
1660 [&](PDLTextFileChunk &chunk) {
1661 chunk.document.getPDLLViewOutput(outputOS,
kind);
1663 [&] { outputOS <<
"\n"
1669 void PDLTextFile::initialize(
const llvm::lsp::URIForFile &uri,
1671 std::vector<llvm::lsp::Diagnostic> &diagnostics) {
1672 version = newVersion;
1678 chunks.emplace_back(std::make_unique<PDLTextFileChunk>(
1679 0, uri, subContents.front(), extraIncludeDirs,
1682 uint64_t lineOffset = subContents.front().count(
'\n');
1683 for (StringRef docContents : llvm::drop_begin(subContents)) {
1684 unsigned currentNumDiags = diagnostics.size();
1685 auto chunk = std::make_unique<PDLTextFileChunk>(
1686 lineOffset, uri, docContents, extraIncludeDirs, diagnostics);
1687 lineOffset += docContents.count(
'\n');
1691 for (llvm::lsp::Diagnostic &
diag :
1692 llvm::drop_begin(diagnostics, currentNumDiags)) {
1693 chunk->adjustLocForChunkOffset(
diag.range);
1695 if (!
diag.relatedInformation)
1697 for (
auto &it : *
diag.relatedInformation)
1698 if (it.location.uri == uri)
1699 chunk->adjustLocForChunkOffset(it.location.range);
1701 chunks.emplace_back(std::move(chunk));
1703 totalNumLines = lineOffset;
1706 PDLTextFile::ChunkIterator
1707 PDLTextFile::getChunkItFor(llvm::lsp::Position &pos) {
1708 if (chunks.size() == 1)
1709 return chunks.begin();
1713 auto it = llvm::upper_bound(
1714 chunks, pos, [](
const llvm::lsp::Position &pos,
const auto &chunk) {
1715 return static_cast<uint64_t
>(pos.line) < chunk->lineOffset;
1717 ChunkIterator chunkIt(it == chunks.end() ? (chunks.end() - 1) : --it);
1718 pos.line -= chunkIt->lineOffset;
1738 llvm::StringMap<std::unique_ptr<PDLTextFile>>
files;
1750 const URIForFile &uri, StringRef contents, int64_t version,
1751 std::vector<llvm::lsp::Diagnostic> &diagnostics) {
1753 std::vector<std::string> additionalIncludeDirs =
impl->options.extraDirs;
1754 const auto &fileInfo =
impl->compilationDatabase.getFileInfo(uri.file());
1755 llvm::append_range(additionalIncludeDirs, fileInfo.includeDirs);
1757 impl->files[uri.file()] = std::make_unique<PDLTextFile>(
1758 uri, contents, version, additionalIncludeDirs, diagnostics);
1763 int64_t version, std::vector<llvm::lsp::Diagnostic> &diagnostics) {
1765 auto it =
impl->files.find(uri.file());
1766 if (it ==
impl->files.end())
1771 if (
failed(it->second->update(uri, version, changes, diagnostics)))
1772 impl->files.erase(it);
1776 auto it =
impl->files.find(uri.file());
1777 if (it ==
impl->files.end())
1778 return std::nullopt;
1780 int64_t version = it->second->getVersion();
1781 impl->files.erase(it);
1786 const URIForFile &uri,
const Position &defPos,
1787 std::vector<llvm::lsp::Location> &locations) {
1788 auto fileIt =
impl->files.find(uri.file());
1789 if (fileIt !=
impl->files.end())
1790 fileIt->second->getLocationsOf(uri, defPos, locations);
1794 const URIForFile &uri,
const Position &pos,
1795 std::vector<llvm::lsp::Location> &references) {
1796 auto fileIt =
impl->files.find(uri.file());
1797 if (fileIt !=
impl->files.end())
1798 fileIt->second->findReferencesOf(uri, pos, references);
1802 const URIForFile &uri, std::vector<DocumentLink> &documentLinks) {
1803 auto fileIt =
impl->files.find(uri.file());
1804 if (fileIt !=
impl->files.end())
1805 return fileIt->second->getDocumentLinks(uri, documentLinks);
1808 std::optional<llvm::lsp::Hover>
1810 auto fileIt =
impl->files.find(uri.file());
1811 if (fileIt !=
impl->files.end())
1812 return fileIt->second->findHover(uri, hoverPos);
1813 return std::nullopt;
1817 const URIForFile &uri, std::vector<DocumentSymbol> &symbols) {
1818 auto fileIt =
impl->files.find(uri.file());
1819 if (fileIt !=
impl->files.end())
1820 fileIt->second->findDocumentSymbols(symbols);
1825 const Position &completePos) {
1826 auto fileIt =
impl->files.find(uri.file());
1827 if (fileIt !=
impl->files.end())
1828 return fileIt->second->getCodeCompletion(uri, completePos);
1829 return CompletionList();
1832 llvm::lsp::SignatureHelp
1834 const Position &helpPos) {
1835 auto fileIt =
impl->files.find(uri.file());
1836 if (fileIt !=
impl->files.end())
1837 return fileIt->second->getSignatureHelp(uri, helpPos);
1838 return SignatureHelp();
1842 std::vector<InlayHint> &inlayHints) {
1843 auto fileIt =
impl->files.find(uri.file());
1844 if (fileIt ==
impl->files.end())
1846 fileIt->second->getInlayHints(uri, range, inlayHints);
1849 llvm::sort(inlayHints);
1850 inlayHints.erase(llvm::unique(inlayHints), inlayHints.end());
1853 std::optional<lsp::PDLLViewOutputResult>
1856 auto fileIt =
impl->files.find(uri.file());
1857 if (fileIt !=
impl->files.end())
1858 return fileIt->second->getPDLLViewOutput(
kind);
1859 return std::nullopt;
static std::string toString(bytecode::Section::ID sectionID)
Stringify the given section ID.
union mlir::linalg::@1243::ArityGroupAndKind::Kind kind
static bool contains(SMRange range, SMLoc loc)
Returns true if the given range contains the given source location.
static std::string diag(const llvm::Value &value)
static std::optional< std::string > getDocumentationFor(llvm::SourceMgr &sourceMgr, const ast::Decl *decl)
Get or extract the documentation for the given decl.
static llvm::lsp::Location getLocationFromLoc(llvm::SourceMgr &mgr, SMRange range, const llvm::lsp::URIForFile &uri)
Returns a language server location from the given source range.
static bool shouldAddHintFor(const ast::Expr *expr, StringRef name)
Returns true if the given name should be added as a hint for expr.
static std::optional< llvm::lsp::Diagnostic > getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr, const ast::Diagnostic &diag, const llvm::lsp::URIForFile &uri)
Convert the given MLIR diagnostic to the LSP form.
static llvm::lsp::URIForFile getURIFromLoc(llvm::SourceMgr &mgr, SMRange loc, const llvm::lsp::URIForFile &mainFileURI)
Returns a language server uri for the given source location.
static bool isMainFileLoc(llvm::SourceMgr &mgr, SMRange loc)
Returns true if the given location is in the main file of the source manager.
static llvm::ManagedStatic< PassManagerOptions > options
static void rewrite(DataFlowSolver &solver, MLIRContext *context, MutableArrayRef< Region > initialRegions)
Rewrite the given regions using the computing analysis.
MLIRContext is the top-level object for a collection of MLIR operations.
Set of flags used to control the behavior of the various IR print methods (e.g.
This class is a utility diagnostic handler for use with llvm::SourceMgr.
This class contains a collection of compilation information for files provided to the language server...
void getLocationsOf(const URIForFile &uri, const Position &defPos, std::vector< Location > &locations)
Return the locations of the object pointed at by the given position.
void getDocumentLinks(const URIForFile &uri, std::vector< DocumentLink > &documentLinks)
Return the document links referenced by the given file.
void getInlayHints(const URIForFile &uri, const Range &range, std::vector< InlayHint > &inlayHints)
Get the inlay hints for the range within the given file.
void addDocument(const URIForFile &uri, StringRef contents, int64_t version, std::vector< Diagnostic > &diagnostics)
Add the document, with the provided version, at the given URI.
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.
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 findDocumentSymbols(const URIForFile &uri, std::vector< DocumentSymbol > &symbols)
Find all of the document symbols within the given file.
std::optional< int64_t > removeDocument(const URIForFile &uri)
Remove the document with the given uri.
CompletionList getCodeCompletion(const URIForFile &uri, const Position &completePos)
Get the code completion list for the position within the given file.
SignatureHelp getSignatureHelp(const URIForFile &uri, const Position &helpPos)
Get the signature help for the position within the given file.
void updateDocument(const URIForFile &uri, ArrayRef< TextDocumentContentChangeEvent > changes, int64_t version, std::vector< Diagnostic > &diagnostics)
Update the document, with the provided version, at the given URI.
std::optional< PDLLViewOutputResult > getPDLLViewOutput(const URIForFile &uri, PDLLViewOutputKind kind)
Get the output of the given PDLL file, or std::nullopt if there is no valid output.
This class provides an abstract interface into the parser for hooking in code completion events.
virtual void codeCompleteConstraintName(ast::Type currentType, bool allowInlineTypeConstraints, const ast::DeclScope *scope)
Signal code completion for a constraint name with an optional decl scope.
virtual void codeCompleteOperationAttributeName(StringRef opName)
Signal code completion for a member access into the given operation type.
virtual void codeCompleteOperationOperandsSignature(std::optional< StringRef > opName, unsigned currentNumOperands)
Signal code completion for the signature of an operation's operands.
virtual void codeCompleteOperationName(StringRef dialectName)
Signal code completion for an operation name in the given dialect.
virtual void codeCompleteOperationResultsSignature(std::optional< StringRef > opName, unsigned currentNumResults)
Signal code completion for the signature of an operation's results.
virtual void codeCompleteDialectName()
Signal code completion for a dialect name.
virtual void codeCompleteOperationMemberAccess(ast::OperationType opType)
Signal code completion for a member access into the given operation type.
virtual void codeCompleteTupleMemberAccess(ast::TupleType tupleType)
Signal code completion for a member access into the given tuple type.
virtual void codeCompletePatternMetadata()
Signal code completion for Pattern metadata.
virtual void codeCompleteCallSignature(const ast::CallableDecl *callable, unsigned currentNumArgs)
Signal code completion for the signature of a callable.
virtual void codeCompleteIncludeFilename(StringRef curPath)
Signal code completion for an include filename.
The class represents an Attribute constraint, and constrains a variable to be an Attribute.
This expression represents a call to a decl, such as a UserConstraintDecl/UserRewriteDecl.
Expr * getCallableExpr() const
Return the callable of this call.
MutableArrayRef< Expr * > getArguments()
Return the arguments of this call.
This decl represents a shared interface for all callable decls.
This class represents the main context of the PDLL AST.
This class represents the base of all "core" constraints.
This class represents a scope for named AST decls.
This class represents the base Decl node.
std::optional< StringRef > getDocComment() const
Return the documentation comment attached to this decl if it has been set.
This class provides a simple implementation of a PDLL diagnostic.
This class represents a base AST Expression node.
Type getType() const
Return the type of this expression.
This class represents a top-level AST module.
This class represents a base AST node.
SMRange getLoc() const
Return the location of this node.
The class represents an Operation constraint, and constrains a variable to be an Operation.
std::optional< StringRef > getName() const
Return the name of the operation, or std::nullopt if there isn't one.
Expr * getRootOpExpr() const
Return the root operation of this rewrite.
This expression represents the structural form of an MLIR Operation.
MutableArrayRef< Expr * > getResultTypes()
Return the result types of this operation.
MutableArrayRef< Expr * > getOperands()
Return the operands of this operation.
This class represents a PDLL type that corresponds to an mlir::Operation.
const ods::Operation * getODSOperation() const
Return the ODS operation that this type refers to, or nullptr if the ODS operation is unknown.
This Decl represents a single Pattern.
const OpRewriteStmt * getRootRewriteStmt() const
Return the root rewrite statement of this pattern.
std::optional< uint16_t > getBenefit() const
Return the benefit of this pattern if specified, or std::nullopt.
bool hasBoundedRewriteRecursion() const
Return if this pattern has bounded rewrite recursion.
This class represents a PDLL tuple type, i.e.
The class represents a Type constraint, and constrains a variable to be a Type.
The class represents a TypeRange constraint, and constrains a variable to be a TypeRange.
The class represents a Value constraint, and constrains a variable to be a Value.
The class represents a ValueRange constraint, and constrains a variable to be a ValueRange.
This Decl represents the definition of a PDLL variable.
const Name & getName() const
Return the name of the decl.
Expr * getInitExpr() const
Return the initializer expression of this statement, or nullptr if there was no initializer.
MutableArrayRef< ConstraintRef > getConstraints()
Return the constraints of this variable.
Type getType() const
Return the type of the decl.
This class represents a generic ODS Attribute constraint.
StringRef getCppClass() const
Return the name of the underlying c++ class of this constraint.
This class provides an ODS representation of a specific operation attribute.
StringRef getSummary() const
Return the summary of this constraint.
StringRef getName() const
Return the unique name of this constraint.
This class contains all of the registered ODS operation classes.
auto getDialects() const
Return a range of all of the registered dialects.
const Dialect * lookupDialect(StringRef name) const
Lookup a dialect registered with the given name, or null if no dialect with that name was inserted.
const Operation * lookupOperation(StringRef name) const
Lookup an operation registered with the given name, or null if no operation with that name is registe...
This class represents an ODS dialect, and contains information on the constructs held within the dial...
const llvm::StringMap< std::unique_ptr< Operation > > & getOperations() const
Return a map of all of the operations registered to this dialect.
This class provides an ODS representation of a specific operation operand or result.
const TypeConstraint & getConstraint() const
Return the constraint of this value.
VariableLengthKind getVariableLengthKind() const
Returns the variable length kind of this value.
StringRef getName() const
Return the name of this value.
This class provides an ODS representation of a specific operation.
StringRef getDescription() const
Returns the description of the operation.
StringRef getSummary() const
Returns the summary of the operation.
ArrayRef< Attribute > getAttributes() const
Returns the attributes of this operation.
StringRef getName() const
Returns the name of the operation.
SMRange getLoc() const
Return the source location of this operation.
ArrayRef< OperandOrResult > getOperands() const
Returns the operands of this operation.
ArrayRef< OperandOrResult > getResults() const
Returns the results of this operation.
This class represents a generic ODS Type constraint.
StringRef getCppClass() const
Return the name of the underlying c++ class of this constraint.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
PDLLViewOutputKind
The type of output to view from PDLL.
void gatherIncludeFiles(llvm::SourceMgr &sourceMgr, SmallVectorImpl< SourceMgrInclude > &includes)
Given a source manager, gather all of the processed include files.
std::optional< std::string > extractSourceDocComment(llvm::SourceMgr &sourceMgr, SMLoc loc)
Extract a documentation comment for the given location within the source manager.
void codegenPDLLToCPP(const ast::Module &astModule, ModuleOp module, raw_ostream &os)
FailureOr< ast::Module * > parsePDLLAST(ast::Context &ctx, llvm::SourceMgr &sourceMgr, bool enableDocumentation=false, CodeCompleteContext *codeCompleteContext=nullptr)
Parse an AST module from the main file of the given source manager.
OwningOpRef< ModuleOp > codegenPDLLToMLIR(MLIRContext *mlirContext, const ast::Context &context, const llvm::SourceMgr &sourceMgr, const ast::Module &module)
Given a PDLL module, generate an MLIR PDL pattern module within the given MLIR context.
Include the generated interface declarations.
const char *const kDefaultSplitMarker
Impl(const Options &options)
lsp::CompilationDatabase compilationDatabase
The compilation database containing additional information for files passed to the server.
llvm::StringMap< std::unique_ptr< PDLTextFile > > files
The files held by the server, mapped by their URI file name.
const Options & options
PDLL LSP options.
Represents the result of viewing the output of a PDLL file.
std::string output
The string representation of the output.
This class represents a single include within a root file.
This class provides a convenient API for interacting with source names.
StringRef getName() const
Return the raw string name.
SMRange getLoc() const
Get the location of this name.