xref: /llvm-project/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp (revision 4f4e2abb1a5ff1225d32410fd02b732d077aa056)
15de12bb7SRiver Riddle //===- TableGenServer.cpp - TableGen Language Server ----------------------===//
25de12bb7SRiver Riddle //
35de12bb7SRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45de12bb7SRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
55de12bb7SRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65de12bb7SRiver Riddle //
75de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
85de12bb7SRiver Riddle 
95de12bb7SRiver Riddle #include "TableGenServer.h"
105de12bb7SRiver Riddle 
113e2ad376SRiver Riddle #include "mlir/Support/IndentedOstream.h"
12305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/CompilationDatabase.h"
13305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/Logging.h"
14305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/Protocol.h"
15305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/SourceMgrUtils.h"
165de12bb7SRiver Riddle #include "llvm/ADT/IntervalMap.h"
178d021670SRiver Riddle #include "llvm/ADT/PointerUnion.h"
185de12bb7SRiver Riddle #include "llvm/ADT/StringMap.h"
195de12bb7SRiver Riddle #include "llvm/Support/Path.h"
205de12bb7SRiver Riddle #include "llvm/TableGen/Parser.h"
215de12bb7SRiver Riddle #include "llvm/TableGen/Record.h"
22a1fe1f5fSKazu Hirata #include <optional>
235de12bb7SRiver Riddle 
245de12bb7SRiver Riddle using namespace mlir;
25429819f2SRahul Joshi using llvm::Record;
26429819f2SRahul Joshi using llvm::RecordKeeper;
27429819f2SRahul Joshi using llvm::RecordVal;
28429819f2SRahul Joshi using llvm::SourceMgr;
295de12bb7SRiver Riddle 
30305d7185SRiver Riddle /// Returns the range of a lexical token given a SMLoc corresponding to the
31305d7185SRiver Riddle /// start of an token location. The range is computed heuristically, and
32305d7185SRiver Riddle /// supports identifier-like tokens, strings, etc.
33305d7185SRiver Riddle static SMRange convertTokenLocToRange(SMLoc loc) {
34305d7185SRiver Riddle   return lsp::convertTokenLocToRange(loc, "$");
35305d7185SRiver Riddle }
36305d7185SRiver Riddle 
375de12bb7SRiver Riddle /// Returns a language server uri for the given source location. `mainFileURI`
385de12bb7SRiver Riddle /// corresponds to the uri for the main file of the source manager.
39429819f2SRahul Joshi static lsp::URIForFile getURIFromLoc(const SourceMgr &mgr, SMLoc loc,
405de12bb7SRiver Riddle                                      const lsp::URIForFile &mainFileURI) {
415de12bb7SRiver Riddle   int bufferId = mgr.FindBufferContainingLoc(loc);
425de12bb7SRiver Riddle   if (bufferId == 0 || bufferId == static_cast<int>(mgr.getMainFileID()))
435de12bb7SRiver Riddle     return mainFileURI;
445de12bb7SRiver Riddle   llvm::Expected<lsp::URIForFile> fileForLoc = lsp::URIForFile::fromFile(
455de12bb7SRiver Riddle       mgr.getBufferInfo(bufferId).Buffer->getBufferIdentifier());
465de12bb7SRiver Riddle   if (fileForLoc)
475de12bb7SRiver Riddle     return *fileForLoc;
485de12bb7SRiver Riddle   lsp::Logger::error("Failed to create URI for include file: {0}",
495de12bb7SRiver Riddle                      llvm::toString(fileForLoc.takeError()));
505de12bb7SRiver Riddle   return mainFileURI;
515de12bb7SRiver Riddle }
525de12bb7SRiver Riddle 
535de12bb7SRiver Riddle /// Returns a language server location from the given source range.
54429819f2SRahul Joshi static lsp::Location getLocationFromLoc(SourceMgr &mgr, SMRange loc,
558d021670SRiver Riddle                                         const lsp::URIForFile &uri) {
568d021670SRiver Riddle   return lsp::Location(getURIFromLoc(mgr, loc.Start, uri),
578d021670SRiver Riddle                        lsp::Range(mgr, loc));
588d021670SRiver Riddle }
59429819f2SRahul Joshi static lsp::Location getLocationFromLoc(SourceMgr &mgr, SMLoc loc,
605de12bb7SRiver Riddle                                         const lsp::URIForFile &uri) {
61305d7185SRiver Riddle   return getLocationFromLoc(mgr, convertTokenLocToRange(loc), uri);
625de12bb7SRiver Riddle }
635de12bb7SRiver Riddle 
645de12bb7SRiver Riddle /// Convert the given TableGen diagnostic to the LSP form.
650a81ace0SKazu Hirata static std::optional<lsp::Diagnostic>
665de12bb7SRiver Riddle getLspDiagnoticFromDiag(const llvm::SMDiagnostic &diag,
675de12bb7SRiver Riddle                         const lsp::URIForFile &uri) {
68429819f2SRahul Joshi   auto *sourceMgr = const_cast<SourceMgr *>(diag.getSourceMgr());
695de12bb7SRiver Riddle   if (!sourceMgr || !diag.getLoc().isValid())
701a36588eSKazu Hirata     return std::nullopt;
715de12bb7SRiver Riddle 
725de12bb7SRiver Riddle   lsp::Diagnostic lspDiag;
735de12bb7SRiver Riddle   lspDiag.source = "tablegen";
745de12bb7SRiver Riddle   lspDiag.category = "Parse Error";
755de12bb7SRiver Riddle 
765de12bb7SRiver Riddle   // Try to grab a file location for this diagnostic.
775de12bb7SRiver Riddle   lsp::Location loc = getLocationFromLoc(*sourceMgr, diag.getLoc(), uri);
785de12bb7SRiver Riddle   lspDiag.range = loc.range;
795de12bb7SRiver Riddle 
805de12bb7SRiver Riddle   // Skip diagnostics that weren't emitted within the main file.
815de12bb7SRiver Riddle   if (loc.uri != uri)
821a36588eSKazu Hirata     return std::nullopt;
835de12bb7SRiver Riddle 
845de12bb7SRiver Riddle   // Convert the severity for the diagnostic.
855de12bb7SRiver Riddle   switch (diag.getKind()) {
86429819f2SRahul Joshi   case SourceMgr::DK_Warning:
875de12bb7SRiver Riddle     lspDiag.severity = lsp::DiagnosticSeverity::Warning;
885de12bb7SRiver Riddle     break;
89429819f2SRahul Joshi   case SourceMgr::DK_Error:
905de12bb7SRiver Riddle     lspDiag.severity = lsp::DiagnosticSeverity::Error;
915de12bb7SRiver Riddle     break;
92429819f2SRahul Joshi   case SourceMgr::DK_Note:
935de12bb7SRiver Riddle     // Notes are emitted separately from the main diagnostic, so we just treat
945de12bb7SRiver Riddle     // them as remarks given that we can't determine the diagnostic to relate
955de12bb7SRiver Riddle     // them to.
96429819f2SRahul Joshi   case SourceMgr::DK_Remark:
975de12bb7SRiver Riddle     lspDiag.severity = lsp::DiagnosticSeverity::Information;
985de12bb7SRiver Riddle     break;
995de12bb7SRiver Riddle   }
1005de12bb7SRiver Riddle   lspDiag.message = diag.getMessage().str();
1015de12bb7SRiver Riddle 
1025de12bb7SRiver Riddle   return lspDiag;
1035de12bb7SRiver Riddle }
1045de12bb7SRiver Riddle 
1053e2ad376SRiver Riddle /// Get the base definition of the given record value, or nullptr if one
1063e2ad376SRiver Riddle /// couldn't be found.
107429819f2SRahul Joshi static std::pair<const Record *, const RecordVal *>
108429819f2SRahul Joshi getBaseValue(const Record *record, const RecordVal *value) {
1093e2ad376SRiver Riddle   if (value->isTemplateArg())
1103e2ad376SRiver Riddle     return {nullptr, nullptr};
1113e2ad376SRiver Riddle 
1123e2ad376SRiver Riddle   // Find a base value for the field in the super classes of the given record.
1133e2ad376SRiver Riddle   // On success, `record` is updated to the new parent record.
1143e2ad376SRiver Riddle   StringRef valueName = value->getName();
11565e69f74SRahul Joshi   auto findValueInSupers = [&](const Record *&record) -> const RecordVal * {
1163e2ad376SRiver Riddle     for (auto [parentRecord, loc] : record->getSuperClasses()) {
1173e2ad376SRiver Riddle       if (auto *newBase = parentRecord->getValue(valueName)) {
1183e2ad376SRiver Riddle         record = parentRecord;
1193e2ad376SRiver Riddle         return newBase;
1203e2ad376SRiver Riddle       }
1213e2ad376SRiver Riddle     }
1223e2ad376SRiver Riddle     return nullptr;
1233e2ad376SRiver Riddle   };
1243e2ad376SRiver Riddle 
1253e2ad376SRiver Riddle   // Try to find the lowest definition of the record value.
126429819f2SRahul Joshi   std::pair<const Record *, const RecordVal *> baseValue = {};
127429819f2SRahul Joshi   while (const RecordVal *newBase = findValueInSupers(record))
1283e2ad376SRiver Riddle     baseValue = {record, newBase};
1293e2ad376SRiver Riddle 
1303e2ad376SRiver Riddle   // Check that the base isn't the same as the current value (e.g. if the value
1313e2ad376SRiver Riddle   // wasn't overridden).
1323e2ad376SRiver Riddle   if (!baseValue.second || baseValue.second->getLoc() == value->getLoc())
1333e2ad376SRiver Riddle     return {nullptr, nullptr};
1343e2ad376SRiver Riddle   return baseValue;
1353e2ad376SRiver Riddle }
1363e2ad376SRiver Riddle 
1375de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
1388d021670SRiver Riddle // TableGenIndex
1398d021670SRiver Riddle //===----------------------------------------------------------------------===//
1408d021670SRiver Riddle 
1418d021670SRiver Riddle namespace {
1428d021670SRiver Riddle /// This class represents a single symbol definition within a TableGen index. It
1438d021670SRiver Riddle /// contains the definition of the symbol, the location of the symbol, and any
1448d021670SRiver Riddle /// recorded references.
1458d021670SRiver Riddle struct TableGenIndexSymbol {
146429819f2SRahul Joshi   TableGenIndexSymbol(const Record *record)
1478d021670SRiver Riddle       : definition(record),
148305d7185SRiver Riddle         defLoc(convertTokenLocToRange(record->getLoc().front())) {}
149429819f2SRahul Joshi   TableGenIndexSymbol(const RecordVal *value)
150305d7185SRiver Riddle       : definition(value), defLoc(convertTokenLocToRange(value->getLoc())) {}
151e00dc16dSRiver Riddle   virtual ~TableGenIndexSymbol() = default;
1528d021670SRiver Riddle 
1533e2ad376SRiver Riddle   // The main definition of the symbol.
154429819f2SRahul Joshi   PointerUnion<const Record *, const RecordVal *> definition;
1558d021670SRiver Riddle 
1568d021670SRiver Riddle   /// The source location of the definition.
1578d021670SRiver Riddle   SMRange defLoc;
1588d021670SRiver Riddle 
1598d021670SRiver Riddle   /// The source location of the references of the definition.
1608d021670SRiver Riddle   SmallVector<SMRange> references;
1618d021670SRiver Riddle };
1623e2ad376SRiver Riddle /// This class represents a single record symbol.
1633e2ad376SRiver Riddle struct TableGenRecordSymbol : public TableGenIndexSymbol {
164429819f2SRahul Joshi   TableGenRecordSymbol(const Record *record) : TableGenIndexSymbol(record) {}
165e00dc16dSRiver Riddle   ~TableGenRecordSymbol() override = default;
1663e2ad376SRiver Riddle 
1673e2ad376SRiver Riddle   static bool classof(const TableGenIndexSymbol *symbol) {
168*4f4e2abbSKazu Hirata     return isa<const Record *>(symbol->definition);
1693e2ad376SRiver Riddle   }
1703e2ad376SRiver Riddle 
1713e2ad376SRiver Riddle   /// Return the value of this symbol.
172*4f4e2abbSKazu Hirata   const Record *getValue() const { return cast<const Record *>(definition); }
1733e2ad376SRiver Riddle };
1743e2ad376SRiver Riddle /// This class represents a single record value symbol.
1753e2ad376SRiver Riddle struct TableGenRecordValSymbol : public TableGenIndexSymbol {
176429819f2SRahul Joshi   TableGenRecordValSymbol(const Record *record, const RecordVal *value)
1773e2ad376SRiver Riddle       : TableGenIndexSymbol(value), record(record) {}
178e00dc16dSRiver Riddle   ~TableGenRecordValSymbol() override = default;
1793e2ad376SRiver Riddle 
1803e2ad376SRiver Riddle   static bool classof(const TableGenIndexSymbol *symbol) {
181*4f4e2abbSKazu Hirata     return isa<const RecordVal *>(symbol->definition);
1823e2ad376SRiver Riddle   }
1833e2ad376SRiver Riddle 
1843e2ad376SRiver Riddle   /// Return the value of this symbol.
185429819f2SRahul Joshi   const RecordVal *getValue() const {
186*4f4e2abbSKazu Hirata     return cast<const RecordVal *>(definition);
1873e2ad376SRiver Riddle   }
1883e2ad376SRiver Riddle 
1893e2ad376SRiver Riddle   /// The parent record of this symbol.
190429819f2SRahul Joshi   const Record *record;
1913e2ad376SRiver Riddle };
1928d021670SRiver Riddle 
1938d021670SRiver Riddle /// This class provides an index for definitions/uses within a TableGen
1948d021670SRiver Riddle /// document. It provides efficient lookup of a definition given an input source
1958d021670SRiver Riddle /// range.
1968d021670SRiver Riddle class TableGenIndex {
1978d021670SRiver Riddle public:
1988d021670SRiver Riddle   TableGenIndex() : intervalMap(allocator) {}
1998d021670SRiver Riddle 
2008d021670SRiver Riddle   /// Initialize the index with the given RecordKeeper.
201429819f2SRahul Joshi   void initialize(const RecordKeeper &records);
2028d021670SRiver Riddle 
2038d021670SRiver Riddle   /// Lookup a symbol for the given location. Returns nullptr if no symbol could
2048d021670SRiver Riddle   /// be found. If provided, `overlappedRange` is set to the range that the
2058d021670SRiver Riddle   /// provided `loc` overlapped with.
2068d021670SRiver Riddle   const TableGenIndexSymbol *lookup(SMLoc loc,
2078d021670SRiver Riddle                                     SMRange *overlappedRange = nullptr) const;
2088d021670SRiver Riddle 
2098d021670SRiver Riddle private:
2108d021670SRiver Riddle   /// The type of interval map used to store source references. SMRange is
2118d021670SRiver Riddle   /// half-open, so we also need to use a half-open interval map.
2128d021670SRiver Riddle   using MapT = llvm::IntervalMap<
2138d021670SRiver Riddle       const char *, const TableGenIndexSymbol *,
2148d021670SRiver Riddle       llvm::IntervalMapImpl::NodeSizer<const char *,
2158d021670SRiver Riddle                                        const TableGenIndexSymbol *>::LeafSize,
2168d021670SRiver Riddle       llvm::IntervalMapHalfOpenInfo<const char *>>;
2178d021670SRiver Riddle 
2183e2ad376SRiver Riddle   /// Get or insert a symbol for the given record.
219429819f2SRahul Joshi   TableGenIndexSymbol *getOrInsertDef(const Record *record) {
2203e2ad376SRiver Riddle     auto it = defToSymbol.try_emplace(record, nullptr);
2213e2ad376SRiver Riddle     if (it.second)
2223e2ad376SRiver Riddle       it.first->second = std::make_unique<TableGenRecordSymbol>(record);
2233e2ad376SRiver Riddle     return &*it.first->second;
2243e2ad376SRiver Riddle   }
2253e2ad376SRiver Riddle   /// Get or insert a symbol for the given record value.
226429819f2SRahul Joshi   TableGenIndexSymbol *getOrInsertDef(const Record *record,
227429819f2SRahul Joshi                                       const RecordVal *value) {
2283e2ad376SRiver Riddle     auto it = defToSymbol.try_emplace(value, nullptr);
2293e2ad376SRiver Riddle     if (it.second) {
2303e2ad376SRiver Riddle       it.first->second =
2313e2ad376SRiver Riddle           std::make_unique<TableGenRecordValSymbol>(record, value);
2323e2ad376SRiver Riddle     }
2333e2ad376SRiver Riddle     return &*it.first->second;
2343e2ad376SRiver Riddle   }
2353e2ad376SRiver Riddle 
2368d021670SRiver Riddle   /// An allocator for the interval map.
2378d021670SRiver Riddle   MapT::Allocator allocator;
2388d021670SRiver Riddle 
2398d021670SRiver Riddle   /// An interval map containing a corresponding definition mapped to a source
2408d021670SRiver Riddle   /// interval.
2418d021670SRiver Riddle   MapT intervalMap;
2428d021670SRiver Riddle 
2438d021670SRiver Riddle   /// A mapping between definitions and their corresponding symbol.
2448d021670SRiver Riddle   DenseMap<const void *, std::unique_ptr<TableGenIndexSymbol>> defToSymbol;
2458d021670SRiver Riddle };
2468d021670SRiver Riddle } // namespace
2478d021670SRiver Riddle 
248429819f2SRahul Joshi void TableGenIndex::initialize(const RecordKeeper &records) {
249e00dc16dSRiver Riddle   intervalMap.clear();
250e00dc16dSRiver Riddle   defToSymbol.clear();
251e00dc16dSRiver Riddle 
2528d021670SRiver Riddle   auto insertRef = [&](TableGenIndexSymbol *sym, SMRange refLoc,
2538d021670SRiver Riddle                        bool isDef = false) {
2548d021670SRiver Riddle     const char *startLoc = refLoc.Start.getPointer();
2558d021670SRiver Riddle     const char *endLoc = refLoc.End.getPointer();
2568d021670SRiver Riddle 
2578d021670SRiver Riddle     // If the location we got was empty, try to lex a token from the start
2588d021670SRiver Riddle     // location.
2598d021670SRiver Riddle     if (startLoc == endLoc) {
260305d7185SRiver Riddle       refLoc = convertTokenLocToRange(SMLoc::getFromPointer(startLoc));
2618d021670SRiver Riddle       startLoc = refLoc.Start.getPointer();
2628d021670SRiver Riddle       endLoc = refLoc.End.getPointer();
2638d021670SRiver Riddle 
2648d021670SRiver Riddle       // If the location is still empty, bail on trying to use this reference
2658d021670SRiver Riddle       // location.
2668d021670SRiver Riddle       if (startLoc == endLoc)
2678d021670SRiver Riddle         return;
2688d021670SRiver Riddle     }
2698d021670SRiver Riddle 
2708d021670SRiver Riddle     // Check to see if a symbol is already attached to this location.
2718d021670SRiver Riddle     // IntervalMap doesn't allow overlapping inserts, and we don't really
2728d021670SRiver Riddle     // want multiple symbols attached to a source location anyways. This
2738d021670SRiver Riddle     // shouldn't really happen in practice, but we should handle it gracefully.
2748d021670SRiver Riddle     if (!intervalMap.overlaps(startLoc, endLoc))
2758d021670SRiver Riddle       intervalMap.insert(startLoc, endLoc, sym);
2768d021670SRiver Riddle 
2778d021670SRiver Riddle     if (!isDef)
2788d021670SRiver Riddle       sym->references.push_back(refLoc);
2798d021670SRiver Riddle   };
2808d021670SRiver Riddle   auto classes =
2818d021670SRiver Riddle       llvm::make_pointee_range(llvm::make_second_range(records.getClasses()));
2828d021670SRiver Riddle   auto defs =
2838d021670SRiver Riddle       llvm::make_pointee_range(llvm::make_second_range(records.getDefs()));
284429819f2SRahul Joshi   for (const Record &def : llvm::concat<Record>(classes, defs)) {
2858d021670SRiver Riddle     auto *sym = getOrInsertDef(&def);
2868d021670SRiver Riddle     insertRef(sym, sym->defLoc, /*isDef=*/true);
2878d021670SRiver Riddle 
2888d021670SRiver Riddle     // Add references to the definition.
2898d021670SRiver Riddle     for (SMLoc loc : def.getLoc().drop_front())
290305d7185SRiver Riddle       insertRef(sym, convertTokenLocToRange(loc));
29150d96f59SRiver Riddle     for (SMRange loc : def.getReferenceLocs())
29250d96f59SRiver Riddle       insertRef(sym, loc);
2938d021670SRiver Riddle 
2948d021670SRiver Riddle     // Add definitions for any values.
295429819f2SRahul Joshi     for (const RecordVal &value : def.getValues()) {
2963e2ad376SRiver Riddle       auto *sym = getOrInsertDef(&def, &value);
2978d021670SRiver Riddle       insertRef(sym, sym->defLoc, /*isDef=*/true);
29850d96f59SRiver Riddle       for (SMRange refLoc : value.getReferenceLocs())
29950d96f59SRiver Riddle         insertRef(sym, refLoc);
3008d021670SRiver Riddle     }
3018d021670SRiver Riddle   }
3028d021670SRiver Riddle }
3038d021670SRiver Riddle 
3048d021670SRiver Riddle const TableGenIndexSymbol *
3058d021670SRiver Riddle TableGenIndex::lookup(SMLoc loc, SMRange *overlappedRange) const {
3068d021670SRiver Riddle   auto it = intervalMap.find(loc.getPointer());
3078d021670SRiver Riddle   if (!it.valid() || loc.getPointer() < it.start())
3088d021670SRiver Riddle     return nullptr;
3098d021670SRiver Riddle 
3108d021670SRiver Riddle   if (overlappedRange) {
3118d021670SRiver Riddle     *overlappedRange = SMRange(SMLoc::getFromPointer(it.start()),
3128d021670SRiver Riddle                                SMLoc::getFromPointer(it.stop()));
3138d021670SRiver Riddle   }
3148d021670SRiver Riddle   return it.value();
3158d021670SRiver Riddle }
3168d021670SRiver Riddle 
3178d021670SRiver Riddle //===----------------------------------------------------------------------===//
3185de12bb7SRiver Riddle // TableGenTextFile
3195de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
3205de12bb7SRiver Riddle 
3215de12bb7SRiver Riddle namespace {
3225de12bb7SRiver Riddle /// This class represents a text file containing one or more TableGen documents.
3235de12bb7SRiver Riddle class TableGenTextFile {
3245de12bb7SRiver Riddle public:
3255de12bb7SRiver Riddle   TableGenTextFile(const lsp::URIForFile &uri, StringRef fileContents,
326dc9fb65cSRiver Riddle                    int64_t version,
327dc9fb65cSRiver Riddle                    const std::vector<std::string> &extraIncludeDirs,
328dc9fb65cSRiver Riddle                    std::vector<lsp::Diagnostic> &diagnostics);
3295de12bb7SRiver Riddle 
3305de12bb7SRiver Riddle   /// Return the current version of this text file.
3315de12bb7SRiver Riddle   int64_t getVersion() const { return version; }
3325de12bb7SRiver Riddle 
3336187178eSRiver Riddle   /// Update the file to the new version using the provided set of content
3346187178eSRiver Riddle   /// changes. Returns failure if the update was unsuccessful.
3356187178eSRiver Riddle   LogicalResult update(const lsp::URIForFile &uri, int64_t newVersion,
3366187178eSRiver Riddle                        ArrayRef<lsp::TextDocumentContentChangeEvent> changes,
3376187178eSRiver Riddle                        std::vector<lsp::Diagnostic> &diagnostics);
3386187178eSRiver Riddle 
339682ca00eSRiver Riddle   //===--------------------------------------------------------------------===//
3408d021670SRiver Riddle   // Definitions and References
3418d021670SRiver Riddle   //===--------------------------------------------------------------------===//
3428d021670SRiver Riddle 
3438d021670SRiver Riddle   void getLocationsOf(const lsp::URIForFile &uri, const lsp::Position &defPos,
3448d021670SRiver Riddle                       std::vector<lsp::Location> &locations);
3458d021670SRiver Riddle   void findReferencesOf(const lsp::URIForFile &uri, const lsp::Position &pos,
3468d021670SRiver Riddle                         std::vector<lsp::Location> &references);
3478d021670SRiver Riddle 
3488d021670SRiver Riddle   //===--------------------------------------------------------------------===//
349682ca00eSRiver Riddle   // Document Links
350682ca00eSRiver Riddle   //===--------------------------------------------------------------------===//
351682ca00eSRiver Riddle 
352682ca00eSRiver Riddle   void getDocumentLinks(const lsp::URIForFile &uri,
353682ca00eSRiver Riddle                         std::vector<lsp::DocumentLink> &links);
354682ca00eSRiver Riddle 
355682ca00eSRiver Riddle   //===--------------------------------------------------------------------===//
356682ca00eSRiver Riddle   // Hover
357682ca00eSRiver Riddle   //===--------------------------------------------------------------------===//
358682ca00eSRiver Riddle 
3591da3a795SFangrui Song   std::optional<lsp::Hover> findHover(const lsp::URIForFile &uri,
360682ca00eSRiver Riddle                                       const lsp::Position &hoverPos);
361429819f2SRahul Joshi   lsp::Hover buildHoverForRecord(const Record *record,
3623e2ad376SRiver Riddle                                  const SMRange &hoverRange);
363429819f2SRahul Joshi   lsp::Hover buildHoverForTemplateArg(const Record *record,
364429819f2SRahul Joshi                                       const RecordVal *value,
3653e2ad376SRiver Riddle                                       const SMRange &hoverRange);
366429819f2SRahul Joshi   lsp::Hover buildHoverForField(const Record *record, const RecordVal *value,
3673e2ad376SRiver Riddle                                 const SMRange &hoverRange);
368682ca00eSRiver Riddle 
3695de12bb7SRiver Riddle private:
3706187178eSRiver Riddle   /// Initialize the text file from the given file contents.
3716187178eSRiver Riddle   void initialize(const lsp::URIForFile &uri, int64_t newVersion,
3726187178eSRiver Riddle                   std::vector<lsp::Diagnostic> &diagnostics);
3736187178eSRiver Riddle 
3745de12bb7SRiver Riddle   /// The full string contents of the file.
3755de12bb7SRiver Riddle   std::string contents;
3765de12bb7SRiver Riddle 
3775de12bb7SRiver Riddle   /// The version of this file.
3785de12bb7SRiver Riddle   int64_t version;
3795de12bb7SRiver Riddle 
3805de12bb7SRiver Riddle   /// The include directories for this file.
3815de12bb7SRiver Riddle   std::vector<std::string> includeDirs;
3825de12bb7SRiver Riddle 
3835de12bb7SRiver Riddle   /// The source manager containing the contents of the input file.
384429819f2SRahul Joshi   SourceMgr sourceMgr;
3855de12bb7SRiver Riddle 
3865de12bb7SRiver Riddle   /// The record keeper containing the parsed tablegen constructs.
387429819f2SRahul Joshi   std::unique_ptr<RecordKeeper> recordKeeper;
388682ca00eSRiver Riddle 
3898d021670SRiver Riddle   /// The index of the parsed file.
3908d021670SRiver Riddle   TableGenIndex index;
3918d021670SRiver Riddle 
392682ca00eSRiver Riddle   /// The set of includes of the parsed file.
393682ca00eSRiver Riddle   SmallVector<lsp::SourceMgrInclude> parsedIncludes;
3945de12bb7SRiver Riddle };
3955de12bb7SRiver Riddle } // namespace
3965de12bb7SRiver Riddle 
397dc9fb65cSRiver Riddle TableGenTextFile::TableGenTextFile(
398dc9fb65cSRiver Riddle     const lsp::URIForFile &uri, StringRef fileContents, int64_t version,
399dc9fb65cSRiver Riddle     const std::vector<std::string> &extraIncludeDirs,
4005de12bb7SRiver Riddle     std::vector<lsp::Diagnostic> &diagnostics)
4015de12bb7SRiver Riddle     : contents(fileContents.str()), version(version) {
4025de12bb7SRiver Riddle   // Build the set of include directories for this file.
4035de12bb7SRiver Riddle   llvm::SmallString<32> uriDirectory(uri.file());
4045de12bb7SRiver Riddle   llvm::sys::path::remove_filename(uriDirectory);
4055de12bb7SRiver Riddle   includeDirs.push_back(uriDirectory.str().str());
406dc9fb65cSRiver Riddle   includeDirs.insert(includeDirs.end(), extraIncludeDirs.begin(),
407dc9fb65cSRiver Riddle                      extraIncludeDirs.end());
4085de12bb7SRiver Riddle 
4096187178eSRiver Riddle   // Initialize the file.
4106187178eSRiver Riddle   initialize(uri, version, diagnostics);
4116187178eSRiver Riddle }
4126187178eSRiver Riddle 
4136187178eSRiver Riddle LogicalResult
4146187178eSRiver Riddle TableGenTextFile::update(const lsp::URIForFile &uri, int64_t newVersion,
4156187178eSRiver Riddle                          ArrayRef<lsp::TextDocumentContentChangeEvent> changes,
4166187178eSRiver Riddle                          std::vector<lsp::Diagnostic> &diagnostics) {
4176187178eSRiver Riddle   if (failed(lsp::TextDocumentContentChangeEvent::applyTo(changes, contents))) {
4186187178eSRiver Riddle     lsp::Logger::error("Failed to update contents of {0}", uri.file());
4196187178eSRiver Riddle     return failure();
4206187178eSRiver Riddle   }
4216187178eSRiver Riddle 
4226187178eSRiver Riddle   // If the file contents were properly changed, reinitialize the text file.
4236187178eSRiver Riddle   initialize(uri, newVersion, diagnostics);
4246187178eSRiver Riddle   return success();
4256187178eSRiver Riddle }
4266187178eSRiver Riddle 
4276187178eSRiver Riddle void TableGenTextFile::initialize(const lsp::URIForFile &uri,
4286187178eSRiver Riddle                                   int64_t newVersion,
4296187178eSRiver Riddle                                   std::vector<lsp::Diagnostic> &diagnostics) {
4306187178eSRiver Riddle   version = newVersion;
431429819f2SRahul Joshi   sourceMgr = SourceMgr();
432429819f2SRahul Joshi   recordKeeper = std::make_unique<RecordKeeper>();
4336187178eSRiver Riddle 
4346187178eSRiver Riddle   // Build a buffer for this file.
4356187178eSRiver Riddle   auto memBuffer = llvm::MemoryBuffer::getMemBuffer(contents, uri.file());
4366187178eSRiver Riddle   if (!memBuffer) {
4376187178eSRiver Riddle     lsp::Logger::error("Failed to create memory buffer for file", uri.file());
4386187178eSRiver Riddle     return;
4396187178eSRiver Riddle   }
4405de12bb7SRiver Riddle   sourceMgr.setIncludeDirs(includeDirs);
4415de12bb7SRiver Riddle   sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
4425de12bb7SRiver Riddle 
443429819f2SRahul Joshi   // This class provides a context argument for the SourceMgr diagnostic
4445de12bb7SRiver Riddle   // handler.
4455de12bb7SRiver Riddle   struct DiagHandlerContext {
4465de12bb7SRiver Riddle     std::vector<lsp::Diagnostic> &diagnostics;
4475de12bb7SRiver Riddle     const lsp::URIForFile &uri;
4485de12bb7SRiver Riddle   } handlerContext{diagnostics, uri};
4495de12bb7SRiver Riddle 
4505de12bb7SRiver Riddle   // Set the diagnostic handler for the tablegen source manager.
4515de12bb7SRiver Riddle   sourceMgr.setDiagHandler(
4525de12bb7SRiver Riddle       [](const llvm::SMDiagnostic &diag, void *rawHandlerContext) {
4535de12bb7SRiver Riddle         auto *ctx = reinterpret_cast<DiagHandlerContext *>(rawHandlerContext);
4545de12bb7SRiver Riddle         if (auto lspDiag = getLspDiagnoticFromDiag(diag, ctx->uri))
4555de12bb7SRiver Riddle           ctx->diagnostics.push_back(*lspDiag);
4565de12bb7SRiver Riddle       },
4575de12bb7SRiver Riddle       &handlerContext);
4586187178eSRiver Riddle   bool failedToParse = llvm::TableGenParseFile(sourceMgr, *recordKeeper);
459682ca00eSRiver Riddle 
460682ca00eSRiver Riddle   // Process all of the include files.
461682ca00eSRiver Riddle   lsp::gatherIncludeFiles(sourceMgr, parsedIncludes);
462682ca00eSRiver Riddle   if (failedToParse)
4635de12bb7SRiver Riddle     return;
4648d021670SRiver Riddle 
4658d021670SRiver Riddle   // If we successfully parsed the file, we can now build the index.
4666187178eSRiver Riddle   index.initialize(*recordKeeper);
4678d021670SRiver Riddle }
4688d021670SRiver Riddle 
4698d021670SRiver Riddle //===----------------------------------------------------------------------===//
4708d021670SRiver Riddle // TableGenTextFile: Definitions and References
4718d021670SRiver Riddle //===----------------------------------------------------------------------===//
4728d021670SRiver Riddle 
4738d021670SRiver Riddle void TableGenTextFile::getLocationsOf(const lsp::URIForFile &uri,
4748d021670SRiver Riddle                                       const lsp::Position &defPos,
4758d021670SRiver Riddle                                       std::vector<lsp::Location> &locations) {
4768d021670SRiver Riddle   SMLoc posLoc = defPos.getAsSMLoc(sourceMgr);
4778d021670SRiver Riddle   const TableGenIndexSymbol *symbol = index.lookup(posLoc);
4788d021670SRiver Riddle   if (!symbol)
4798d021670SRiver Riddle     return;
4808d021670SRiver Riddle 
48199e24123SRiver Riddle   // If this symbol is a record value and the def position is already the def of
48299e24123SRiver Riddle   // the symbol, check to see if the value has a base definition. This allows
48399e24123SRiver Riddle   // for a "go-to-def" on a "let" to resolve the definition in the base class.
48499e24123SRiver Riddle   auto *valSym = dyn_cast<TableGenRecordValSymbol>(symbol);
48599e24123SRiver Riddle   if (valSym && lsp::contains(valSym->defLoc, posLoc)) {
48699e24123SRiver Riddle     if (auto *val = getBaseValue(valSym->record, valSym->getValue()).second) {
48799e24123SRiver Riddle       locations.push_back(getLocationFromLoc(sourceMgr, val->getLoc(), uri));
48899e24123SRiver Riddle       return;
48999e24123SRiver Riddle     }
49099e24123SRiver Riddle   }
49199e24123SRiver Riddle 
4928d021670SRiver Riddle   locations.push_back(getLocationFromLoc(sourceMgr, symbol->defLoc, uri));
4938d021670SRiver Riddle }
4948d021670SRiver Riddle 
4958d021670SRiver Riddle void TableGenTextFile::findReferencesOf(
4968d021670SRiver Riddle     const lsp::URIForFile &uri, const lsp::Position &pos,
4978d021670SRiver Riddle     std::vector<lsp::Location> &references) {
4988d021670SRiver Riddle   SMLoc posLoc = pos.getAsSMLoc(sourceMgr);
4998d021670SRiver Riddle   const TableGenIndexSymbol *symbol = index.lookup(posLoc);
5008d021670SRiver Riddle   if (!symbol)
5018d021670SRiver Riddle     return;
5028d021670SRiver Riddle 
5038d021670SRiver Riddle   references.push_back(getLocationFromLoc(sourceMgr, symbol->defLoc, uri));
5048d021670SRiver Riddle   for (SMRange refLoc : symbol->references)
5058d021670SRiver Riddle     references.push_back(getLocationFromLoc(sourceMgr, refLoc, uri));
5065de12bb7SRiver Riddle }
5075de12bb7SRiver Riddle 
508682ca00eSRiver Riddle //===--------------------------------------------------------------------===//
509682ca00eSRiver Riddle // TableGenTextFile: Document Links
510682ca00eSRiver Riddle //===--------------------------------------------------------------------===//
511682ca00eSRiver Riddle 
512682ca00eSRiver Riddle void TableGenTextFile::getDocumentLinks(const lsp::URIForFile &uri,
513682ca00eSRiver Riddle                                         std::vector<lsp::DocumentLink> &links) {
514682ca00eSRiver Riddle   for (const lsp::SourceMgrInclude &include : parsedIncludes)
515682ca00eSRiver Riddle     links.emplace_back(include.range, include.uri);
516682ca00eSRiver Riddle }
517682ca00eSRiver Riddle 
518682ca00eSRiver Riddle //===----------------------------------------------------------------------===//
519682ca00eSRiver Riddle // TableGenTextFile: Hover
520682ca00eSRiver Riddle //===----------------------------------------------------------------------===//
521682ca00eSRiver Riddle 
5221da3a795SFangrui Song std::optional<lsp::Hover>
523682ca00eSRiver Riddle TableGenTextFile::findHover(const lsp::URIForFile &uri,
524682ca00eSRiver Riddle                             const lsp::Position &hoverPos) {
525682ca00eSRiver Riddle   // Check for a reference to an include.
526682ca00eSRiver Riddle   for (const lsp::SourceMgrInclude &include : parsedIncludes)
527682ca00eSRiver Riddle     if (include.range.contains(hoverPos))
528682ca00eSRiver Riddle       return include.buildHover();
5293e2ad376SRiver Riddle 
5303e2ad376SRiver Riddle   // Find the symbol at the given location.
5313e2ad376SRiver Riddle   SMRange hoverRange;
5323e2ad376SRiver Riddle   SMLoc posLoc = hoverPos.getAsSMLoc(sourceMgr);
5333e2ad376SRiver Riddle   const TableGenIndexSymbol *symbol = index.lookup(posLoc, &hoverRange);
5343e2ad376SRiver Riddle   if (!symbol)
5351a36588eSKazu Hirata     return std::nullopt;
5363e2ad376SRiver Riddle 
5373e2ad376SRiver Riddle   // Build hover for a Record.
5383e2ad376SRiver Riddle   if (auto *record = dyn_cast<TableGenRecordSymbol>(symbol))
5393e2ad376SRiver Riddle     return buildHoverForRecord(record->getValue(), hoverRange);
5403e2ad376SRiver Riddle 
5413e2ad376SRiver Riddle   // Build hover for a RecordVal, which is either a template argument or a
5423e2ad376SRiver Riddle   // field.
5433e2ad376SRiver Riddle   auto *recordVal = cast<TableGenRecordValSymbol>(symbol);
544429819f2SRahul Joshi   const RecordVal *value = recordVal->getValue();
5453e2ad376SRiver Riddle   if (value->isTemplateArg())
5463e2ad376SRiver Riddle     return buildHoverForTemplateArg(recordVal->record, value, hoverRange);
5473e2ad376SRiver Riddle   return buildHoverForField(recordVal->record, value, hoverRange);
5483e2ad376SRiver Riddle }
5493e2ad376SRiver Riddle 
550429819f2SRahul Joshi lsp::Hover TableGenTextFile::buildHoverForRecord(const Record *record,
5513e2ad376SRiver Riddle                                                  const SMRange &hoverRange) {
5523e2ad376SRiver Riddle   lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
5533e2ad376SRiver Riddle   {
5543e2ad376SRiver Riddle     llvm::raw_string_ostream hoverOS(hover.contents.value);
5553e2ad376SRiver Riddle 
5563e2ad376SRiver Riddle     // Format the type of record this is.
5573e2ad376SRiver Riddle     if (record->isClass()) {
5583e2ad376SRiver Riddle       hoverOS << "**class** `" << record->getName() << "`";
5593e2ad376SRiver Riddle     } else if (record->isAnonymous()) {
5603e2ad376SRiver Riddle       hoverOS << "**anonymous class**";
5613e2ad376SRiver Riddle     } else {
5623e2ad376SRiver Riddle       hoverOS << "**def** `" << record->getName() << "`";
5633e2ad376SRiver Riddle     }
5643e2ad376SRiver Riddle     hoverOS << "\n***\n";
5653e2ad376SRiver Riddle 
5663e2ad376SRiver Riddle     // Check if this record has summary/description fields. These are often used
5673e2ad376SRiver Riddle     // to hold documentation for the record.
5683e2ad376SRiver Riddle     auto printAndFormatField = [&](StringRef fieldName) {
5693e2ad376SRiver Riddle       // Check that the record actually has the given field, and that it's a
5703e2ad376SRiver Riddle       // string.
571429819f2SRahul Joshi       const RecordVal *value = record->getValue(fieldName);
5723e2ad376SRiver Riddle       if (!value || !value->getValue())
5733e2ad376SRiver Riddle         return;
5743e2ad376SRiver Riddle       auto *stringValue = dyn_cast<llvm::StringInit>(value->getValue());
5753e2ad376SRiver Riddle       if (!stringValue)
5763e2ad376SRiver Riddle         return;
5773e2ad376SRiver Riddle 
5783e2ad376SRiver Riddle       raw_indented_ostream ros(hoverOS);
5793e2ad376SRiver Riddle       ros.printReindented(stringValue->getValue().rtrim(" \t"));
5803e2ad376SRiver Riddle       hoverOS << "\n***\n";
5813e2ad376SRiver Riddle     };
5823e2ad376SRiver Riddle     printAndFormatField("summary");
5833e2ad376SRiver Riddle     printAndFormatField("description");
5843e2ad376SRiver Riddle 
5853e2ad376SRiver Riddle     // Check for documentation in the source file.
5860a81ace0SKazu Hirata     if (std::optional<std::string> doc =
5873e2ad376SRiver Riddle             lsp::extractSourceDocComment(sourceMgr, record->getLoc().front())) {
5883e2ad376SRiver Riddle       hoverOS << "\n" << *doc << "\n";
5893e2ad376SRiver Riddle     }
5903e2ad376SRiver Riddle   }
5913e2ad376SRiver Riddle   return hover;
5923e2ad376SRiver Riddle }
5933e2ad376SRiver Riddle 
594429819f2SRahul Joshi lsp::Hover TableGenTextFile::buildHoverForTemplateArg(
595429819f2SRahul Joshi     const Record *record, const RecordVal *value, const SMRange &hoverRange) {
5963e2ad376SRiver Riddle   lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
5973e2ad376SRiver Riddle   {
5983e2ad376SRiver Riddle     llvm::raw_string_ostream hoverOS(hover.contents.value);
5993e2ad376SRiver Riddle     StringRef name = value->getName().rsplit(':').second;
6003e2ad376SRiver Riddle 
6013e2ad376SRiver Riddle     hoverOS << "**template arg** `" << name << "`\n***\nType: `";
6023e2ad376SRiver Riddle     value->getType()->print(hoverOS);
6033e2ad376SRiver Riddle     hoverOS << "`\n";
6043e2ad376SRiver Riddle   }
6053e2ad376SRiver Riddle   return hover;
6063e2ad376SRiver Riddle }
6073e2ad376SRiver Riddle 
608429819f2SRahul Joshi lsp::Hover TableGenTextFile::buildHoverForField(const Record *record,
609429819f2SRahul Joshi                                                 const RecordVal *value,
6103e2ad376SRiver Riddle                                                 const SMRange &hoverRange) {
6113e2ad376SRiver Riddle   lsp::Hover hover(lsp::Range(sourceMgr, hoverRange));
6123e2ad376SRiver Riddle   {
6133e2ad376SRiver Riddle     llvm::raw_string_ostream hoverOS(hover.contents.value);
6143e2ad376SRiver Riddle     hoverOS << "**field** `" << value->getName() << "`\n***\nType: `";
6153e2ad376SRiver Riddle     value->getType()->print(hoverOS);
6163e2ad376SRiver Riddle     hoverOS << "`\n***\n";
6173e2ad376SRiver Riddle 
6183e2ad376SRiver Riddle     // Check for documentation in the source file.
6190a81ace0SKazu Hirata     if (std::optional<std::string> doc =
6203e2ad376SRiver Riddle             lsp::extractSourceDocComment(sourceMgr, value->getLoc())) {
6213e2ad376SRiver Riddle       hoverOS << "\n" << *doc << "\n";
6223e2ad376SRiver Riddle       hoverOS << "\n***\n";
6233e2ad376SRiver Riddle     }
6243e2ad376SRiver Riddle 
6253e2ad376SRiver Riddle     // Check to see if there is a base value that we can use for
6263e2ad376SRiver Riddle     // documentation.
6273e2ad376SRiver Riddle     auto [baseRecord, baseValue] = getBaseValue(record, value);
6283e2ad376SRiver Riddle     if (baseValue) {
6290a81ace0SKazu Hirata       if (std::optional<std::string> doc =
6303e2ad376SRiver Riddle               lsp::extractSourceDocComment(sourceMgr, baseValue->getLoc())) {
6313e2ad376SRiver Riddle         hoverOS << "\n *From `" << baseRecord->getName() << "`*:\n\n"
6323e2ad376SRiver Riddle                 << *doc << "\n";
6333e2ad376SRiver Riddle       }
6343e2ad376SRiver Riddle     }
6353e2ad376SRiver Riddle   }
6363e2ad376SRiver Riddle   return hover;
637682ca00eSRiver Riddle }
638682ca00eSRiver Riddle 
6395de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
6405de12bb7SRiver Riddle // TableGenServer::Impl
6415de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
6425de12bb7SRiver Riddle 
6435de12bb7SRiver Riddle struct lsp::TableGenServer::Impl {
644dc9fb65cSRiver Riddle   explicit Impl(const Options &options)
645dc9fb65cSRiver Riddle       : options(options), compilationDatabase(options.compilationDatabases) {}
646dc9fb65cSRiver Riddle 
647dc9fb65cSRiver Riddle   /// TableGen LSP options.
648dc9fb65cSRiver Riddle   const Options &options;
649dc9fb65cSRiver Riddle 
650dc9fb65cSRiver Riddle   /// The compilation database containing additional information for files
651dc9fb65cSRiver Riddle   /// passed to the server.
652dc9fb65cSRiver Riddle   lsp::CompilationDatabase compilationDatabase;
653dc9fb65cSRiver Riddle 
6545de12bb7SRiver Riddle   /// The files held by the server, mapped by their URI file name.
6555de12bb7SRiver Riddle   llvm::StringMap<std::unique_ptr<TableGenTextFile>> files;
6565de12bb7SRiver Riddle };
6575de12bb7SRiver Riddle 
6585de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
6595de12bb7SRiver Riddle // TableGenServer
6605de12bb7SRiver Riddle //===----------------------------------------------------------------------===//
6615de12bb7SRiver Riddle 
662dc9fb65cSRiver Riddle lsp::TableGenServer::TableGenServer(const Options &options)
663dc9fb65cSRiver Riddle     : impl(std::make_unique<Impl>(options)) {}
6645de12bb7SRiver Riddle lsp::TableGenServer::~TableGenServer() = default;
6655de12bb7SRiver Riddle 
6666187178eSRiver Riddle void lsp::TableGenServer::addDocument(const URIForFile &uri, StringRef contents,
6676187178eSRiver Riddle                                       int64_t version,
6685de12bb7SRiver Riddle                                       std::vector<Diagnostic> &diagnostics) {
669dc9fb65cSRiver Riddle   // Build the set of additional include directories.
670dc9fb65cSRiver Riddle   std::vector<std::string> additionalIncludeDirs = impl->options.extraDirs;
671dc9fb65cSRiver Riddle   const auto &fileInfo = impl->compilationDatabase.getFileInfo(uri.file());
672dc9fb65cSRiver Riddle   llvm::append_range(additionalIncludeDirs, fileInfo.includeDirs);
673dc9fb65cSRiver Riddle 
674dc9fb65cSRiver Riddle   impl->files[uri.file()] = std::make_unique<TableGenTextFile>(
675dc9fb65cSRiver Riddle       uri, contents, version, additionalIncludeDirs, diagnostics);
6765de12bb7SRiver Riddle }
6775de12bb7SRiver Riddle 
6786187178eSRiver Riddle void lsp::TableGenServer::updateDocument(
6796187178eSRiver Riddle     const URIForFile &uri, ArrayRef<TextDocumentContentChangeEvent> changes,
6806187178eSRiver Riddle     int64_t version, std::vector<Diagnostic> &diagnostics) {
6816187178eSRiver Riddle   // Check that we actually have a document for this uri.
6826187178eSRiver Riddle   auto it = impl->files.find(uri.file());
6836187178eSRiver Riddle   if (it == impl->files.end())
6846187178eSRiver Riddle     return;
6856187178eSRiver Riddle 
6866187178eSRiver Riddle   // Try to update the document. If we fail, erase the file from the server. A
6876187178eSRiver Riddle   // failed updated generally means we've fallen out of sync somewhere.
6886187178eSRiver Riddle   if (failed(it->second->update(uri, version, changes, diagnostics)))
6896187178eSRiver Riddle     impl->files.erase(it);
6906187178eSRiver Riddle }
6916187178eSRiver Riddle 
6920a81ace0SKazu Hirata std::optional<int64_t>
6930a81ace0SKazu Hirata lsp::TableGenServer::removeDocument(const URIForFile &uri) {
6945de12bb7SRiver Riddle   auto it = impl->files.find(uri.file());
6955de12bb7SRiver Riddle   if (it == impl->files.end())
6961a36588eSKazu Hirata     return std::nullopt;
6975de12bb7SRiver Riddle 
6985de12bb7SRiver Riddle   int64_t version = it->second->getVersion();
6995de12bb7SRiver Riddle   impl->files.erase(it);
7005de12bb7SRiver Riddle   return version;
7015de12bb7SRiver Riddle }
702682ca00eSRiver Riddle 
7038d021670SRiver Riddle void lsp::TableGenServer::getLocationsOf(const URIForFile &uri,
7048d021670SRiver Riddle                                          const Position &defPos,
7058d021670SRiver Riddle                                          std::vector<Location> &locations) {
7068d021670SRiver Riddle   auto fileIt = impl->files.find(uri.file());
7078d021670SRiver Riddle   if (fileIt != impl->files.end())
7088d021670SRiver Riddle     fileIt->second->getLocationsOf(uri, defPos, locations);
7098d021670SRiver Riddle }
7108d021670SRiver Riddle 
7118d021670SRiver Riddle void lsp::TableGenServer::findReferencesOf(const URIForFile &uri,
7128d021670SRiver Riddle                                            const Position &pos,
7138d021670SRiver Riddle                                            std::vector<Location> &references) {
7148d021670SRiver Riddle   auto fileIt = impl->files.find(uri.file());
7158d021670SRiver Riddle   if (fileIt != impl->files.end())
7168d021670SRiver Riddle     fileIt->second->findReferencesOf(uri, pos, references);
7178d021670SRiver Riddle }
7188d021670SRiver Riddle 
719682ca00eSRiver Riddle void lsp::TableGenServer::getDocumentLinks(
720682ca00eSRiver Riddle     const URIForFile &uri, std::vector<DocumentLink> &documentLinks) {
721682ca00eSRiver Riddle   auto fileIt = impl->files.find(uri.file());
722682ca00eSRiver Riddle   if (fileIt != impl->files.end())
723682ca00eSRiver Riddle     return fileIt->second->getDocumentLinks(uri, documentLinks);
724682ca00eSRiver Riddle }
725682ca00eSRiver Riddle 
7261da3a795SFangrui Song std::optional<lsp::Hover>
7271da3a795SFangrui Song lsp::TableGenServer::findHover(const URIForFile &uri,
728682ca00eSRiver Riddle                                const Position &hoverPos) {
729682ca00eSRiver Riddle   auto fileIt = impl->files.find(uri.file());
730682ca00eSRiver Riddle   if (fileIt != impl->files.end())
731682ca00eSRiver Riddle     return fileIt->second->findHover(uri, hoverPos);
7321a36588eSKazu Hirata   return std::nullopt;
733682ca00eSRiver Riddle }
734