17bc52733SRiver Riddle //===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
27bc52733SRiver Riddle //
37bc52733SRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47bc52733SRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
57bc52733SRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67bc52733SRiver Riddle //
77bc52733SRiver Riddle //===----------------------------------------------------------------------===//
87bc52733SRiver Riddle //
97bc52733SRiver Riddle // This file contains the serialization code for the LSP structs.
107bc52733SRiver Riddle //
117bc52733SRiver Riddle //===----------------------------------------------------------------------===//
127bc52733SRiver Riddle
13305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/Protocol.h"
14305d7185SRiver Riddle #include "mlir/Tools/lsp-server-support/Logging.h"
157bc52733SRiver Riddle #include "llvm/ADT/Hashing.h"
167bc52733SRiver Riddle #include "llvm/ADT/SmallString.h"
17b0abd489SElliot Goodrich #include "llvm/ADT/StringExtras.h"
18f7b8a70eSRiver Riddle #include "llvm/ADT/StringSet.h"
197bc52733SRiver Riddle #include "llvm/Support/ErrorHandling.h"
207bc52733SRiver Riddle #include "llvm/Support/Format.h"
217bc52733SRiver Riddle #include "llvm/Support/FormatVariadic.h"
227bc52733SRiver Riddle #include "llvm/Support/JSON.h"
236187178eSRiver Riddle #include "llvm/Support/MemoryBuffer.h"
247bc52733SRiver Riddle #include "llvm/Support/Path.h"
257bc52733SRiver Riddle #include "llvm/Support/raw_ostream.h"
267bc52733SRiver Riddle
277bc52733SRiver Riddle using namespace mlir;
287bc52733SRiver Riddle using namespace mlir::lsp;
297bc52733SRiver Riddle
307bc52733SRiver Riddle // Helper that doesn't treat `null` and absent fields as failures.
317bc52733SRiver Riddle template <typename T>
mapOptOrNull(const llvm::json::Value & params,llvm::StringLiteral prop,T & out,llvm::json::Path path)327bc52733SRiver Riddle static bool mapOptOrNull(const llvm::json::Value ¶ms,
337bc52733SRiver Riddle llvm::StringLiteral prop, T &out,
347bc52733SRiver Riddle llvm::json::Path path) {
357bc52733SRiver Riddle const llvm::json::Object *o = params.getAsObject();
367bc52733SRiver Riddle assert(o);
377bc52733SRiver Riddle
387bc52733SRiver Riddle // Field is missing or null.
397bc52733SRiver Riddle auto *v = o->get(prop);
40037f0995SKazu Hirata if (!v || v->getAsNull())
417bc52733SRiver Riddle return true;
427bc52733SRiver Riddle return fromJSON(*v, out, path.field(prop));
437bc52733SRiver Riddle }
447bc52733SRiver Riddle
457bc52733SRiver Riddle //===----------------------------------------------------------------------===//
467bc52733SRiver Riddle // LSPError
477bc52733SRiver Riddle //===----------------------------------------------------------------------===//
487bc52733SRiver Riddle
497bc52733SRiver Riddle char LSPError::ID;
507bc52733SRiver Riddle
517bc52733SRiver Riddle //===----------------------------------------------------------------------===//
527bc52733SRiver Riddle // URIForFile
537bc52733SRiver Riddle //===----------------------------------------------------------------------===//
547bc52733SRiver Riddle
isWindowsPath(StringRef path)557bc52733SRiver Riddle static bool isWindowsPath(StringRef path) {
567bc52733SRiver Riddle return path.size() > 1 && llvm::isAlpha(path[0]) && path[1] == ':';
577bc52733SRiver Riddle }
587bc52733SRiver Riddle
isNetworkPath(StringRef path)597bc52733SRiver Riddle static bool isNetworkPath(StringRef path) {
607bc52733SRiver Riddle return path.size() > 2 && path[0] == path[1] &&
617bc52733SRiver Riddle llvm::sys::path::is_separator(path[0]);
627bc52733SRiver Riddle }
637bc52733SRiver Riddle
shouldEscapeInURI(unsigned char c)647bc52733SRiver Riddle static bool shouldEscapeInURI(unsigned char c) {
657bc52733SRiver Riddle // Unreserved characters.
667bc52733SRiver Riddle if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
677bc52733SRiver Riddle (c >= '0' && c <= '9'))
687bc52733SRiver Riddle return false;
697bc52733SRiver Riddle
707bc52733SRiver Riddle switch (c) {
717bc52733SRiver Riddle case '-':
727bc52733SRiver Riddle case '_':
737bc52733SRiver Riddle case '.':
747bc52733SRiver Riddle case '~':
757bc52733SRiver Riddle // '/' is only reserved when parsing.
767bc52733SRiver Riddle case '/':
777bc52733SRiver Riddle // ':' is only reserved for relative URI paths, which we doesn't produce.
787bc52733SRiver Riddle case ':':
797bc52733SRiver Riddle return false;
807bc52733SRiver Riddle }
817bc52733SRiver Riddle return true;
827bc52733SRiver Riddle }
837bc52733SRiver Riddle
847bc52733SRiver Riddle /// Encodes a string according to percent-encoding.
857bc52733SRiver Riddle /// - Unreserved characters are not escaped.
867bc52733SRiver Riddle /// - Reserved characters always escaped with exceptions like '/'.
877bc52733SRiver Riddle /// - All other characters are escaped.
percentEncode(StringRef content,std::string & out)887bc52733SRiver Riddle static void percentEncode(StringRef content, std::string &out) {
897bc52733SRiver Riddle for (unsigned char c : content) {
907bc52733SRiver Riddle if (shouldEscapeInURI(c)) {
917bc52733SRiver Riddle out.push_back('%');
927bc52733SRiver Riddle out.push_back(llvm::hexdigit(c / 16));
937bc52733SRiver Riddle out.push_back(llvm::hexdigit(c % 16));
947bc52733SRiver Riddle } else {
957bc52733SRiver Riddle out.push_back(c);
967bc52733SRiver Riddle }
977bc52733SRiver Riddle }
987bc52733SRiver Riddle }
997bc52733SRiver Riddle
1007bc52733SRiver Riddle /// Decodes a string according to percent-encoding.
percentDecode(StringRef content)1017bc52733SRiver Riddle static std::string percentDecode(StringRef content) {
1027bc52733SRiver Riddle std::string result;
1037bc52733SRiver Riddle for (auto i = content.begin(), e = content.end(); i != e; ++i) {
1047bc52733SRiver Riddle if (*i != '%') {
1057bc52733SRiver Riddle result += *i;
1067bc52733SRiver Riddle continue;
1077bc52733SRiver Riddle }
1087bc52733SRiver Riddle if (*i == '%' && i + 2 < content.end() && llvm::isHexDigit(*(i + 1)) &&
1097bc52733SRiver Riddle llvm::isHexDigit(*(i + 2))) {
1107bc52733SRiver Riddle result.push_back(llvm::hexFromNibbles(*(i + 1), *(i + 2)));
1117bc52733SRiver Riddle i += 2;
1127bc52733SRiver Riddle } else {
1137bc52733SRiver Riddle result.push_back(*i);
1147bc52733SRiver Riddle }
1157bc52733SRiver Riddle }
1167bc52733SRiver Riddle return result;
1177bc52733SRiver Riddle }
1187bc52733SRiver Riddle
119f7b8a70eSRiver Riddle /// Return the set containing the supported URI schemes.
getSupportedSchemes()120f7b8a70eSRiver Riddle static StringSet<> &getSupportedSchemes() {
121f7b8a70eSRiver Riddle static StringSet<> schemes({"file", "test"});
122f7b8a70eSRiver Riddle return schemes;
123f7b8a70eSRiver Riddle }
124f7b8a70eSRiver Riddle
125f7b8a70eSRiver Riddle /// Returns true if the given scheme is structurally valid, i.e. it does not
126f7b8a70eSRiver Riddle /// contain any invalid scheme characters. This does not check that the scheme
127f7b8a70eSRiver Riddle /// is actually supported.
isStructurallyValidScheme(StringRef scheme)128f7b8a70eSRiver Riddle static bool isStructurallyValidScheme(StringRef scheme) {
1297bc52733SRiver Riddle if (scheme.empty())
1307bc52733SRiver Riddle return false;
1317bc52733SRiver Riddle if (!llvm::isAlpha(scheme[0]))
1327bc52733SRiver Riddle return false;
1336d9cd919SKazu Hirata return llvm::all_of(llvm::drop_begin(scheme), [](char c) {
1347bc52733SRiver Riddle return llvm::isAlnum(c) || c == '+' || c == '.' || c == '-';
1357bc52733SRiver Riddle });
1367bc52733SRiver Riddle }
1377bc52733SRiver Riddle
uriFromAbsolutePath(StringRef absolutePath,StringRef scheme)138f7b8a70eSRiver Riddle static llvm::Expected<std::string> uriFromAbsolutePath(StringRef absolutePath,
139f7b8a70eSRiver Riddle StringRef scheme) {
1407bc52733SRiver Riddle std::string body;
1417bc52733SRiver Riddle StringRef authority;
1427bc52733SRiver Riddle StringRef root = llvm::sys::path::root_name(absolutePath);
1437bc52733SRiver Riddle if (isNetworkPath(root)) {
1447bc52733SRiver Riddle // Windows UNC paths e.g. \\server\share => file://server/share
1457bc52733SRiver Riddle authority = root.drop_front(2);
1467bc52733SRiver Riddle absolutePath.consume_front(root);
1477bc52733SRiver Riddle } else if (isWindowsPath(root)) {
1487bc52733SRiver Riddle // Windows paths e.g. X:\path => file:///X:/path
1497bc52733SRiver Riddle body = "/";
1507bc52733SRiver Riddle }
1517bc52733SRiver Riddle body += llvm::sys::path::convert_to_slash(absolutePath);
1527bc52733SRiver Riddle
153f7b8a70eSRiver Riddle std::string uri = scheme.str() + ":";
1547bc52733SRiver Riddle if (authority.empty() && body.empty())
1557bc52733SRiver Riddle return uri;
1567bc52733SRiver Riddle
1577bc52733SRiver Riddle // If authority if empty, we only print body if it starts with "/"; otherwise,
1587bc52733SRiver Riddle // the URI is invalid.
15988d319a2SKazu Hirata if (!authority.empty() || StringRef(body).starts_with("/")) {
1607bc52733SRiver Riddle uri.append("//");
1617bc52733SRiver Riddle percentEncode(authority, uri);
1627bc52733SRiver Riddle }
1637bc52733SRiver Riddle percentEncode(body, uri);
1647bc52733SRiver Riddle return uri;
1657bc52733SRiver Riddle }
1667bc52733SRiver Riddle
getAbsolutePath(StringRef authority,StringRef body)1677bc52733SRiver Riddle static llvm::Expected<std::string> getAbsolutePath(StringRef authority,
1687bc52733SRiver Riddle StringRef body) {
16988d319a2SKazu Hirata if (!body.starts_with("/"))
1707bc52733SRiver Riddle return llvm::createStringError(
1717bc52733SRiver Riddle llvm::inconvertibleErrorCode(),
1727bc52733SRiver Riddle "File scheme: expect body to be an absolute path starting "
1737bc52733SRiver Riddle "with '/': " +
1747bc52733SRiver Riddle body);
1757bc52733SRiver Riddle SmallString<128> path;
1767bc52733SRiver Riddle if (!authority.empty()) {
1777bc52733SRiver Riddle // Windows UNC paths e.g. file://server/share => \\server\share
1787bc52733SRiver Riddle ("//" + authority).toVector(path);
1797bc52733SRiver Riddle } else if (isWindowsPath(body.substr(1))) {
1807bc52733SRiver Riddle // Windows paths e.g. file:///X:/path => X:\path
1817bc52733SRiver Riddle body.consume_front("/");
1827bc52733SRiver Riddle }
1837bc52733SRiver Riddle path.append(body);
1847bc52733SRiver Riddle llvm::sys::path::native(path);
1857bc52733SRiver Riddle return std::string(path);
1867bc52733SRiver Riddle }
1877bc52733SRiver Riddle
parseFilePathFromURI(StringRef origUri)1887bc52733SRiver Riddle static llvm::Expected<std::string> parseFilePathFromURI(StringRef origUri) {
1897bc52733SRiver Riddle StringRef uri = origUri;
1907bc52733SRiver Riddle
1917bc52733SRiver Riddle // Decode the scheme of the URI.
1927bc52733SRiver Riddle size_t pos = uri.find(':');
1937bc52733SRiver Riddle if (pos == StringRef::npos)
1947bc52733SRiver Riddle return llvm::createStringError(llvm::inconvertibleErrorCode(),
1957bc52733SRiver Riddle "Scheme must be provided in URI: " +
1967bc52733SRiver Riddle origUri);
1977bc52733SRiver Riddle StringRef schemeStr = uri.substr(0, pos);
1987bc52733SRiver Riddle std::string uriScheme = percentDecode(schemeStr);
199f7b8a70eSRiver Riddle if (!isStructurallyValidScheme(uriScheme))
2007bc52733SRiver Riddle return llvm::createStringError(llvm::inconvertibleErrorCode(),
2017bc52733SRiver Riddle "Invalid scheme: " + schemeStr +
2027bc52733SRiver Riddle " (decoded: " + uriScheme + ")");
2037bc52733SRiver Riddle uri = uri.substr(pos + 1);
2047bc52733SRiver Riddle
2057bc52733SRiver Riddle // Decode the authority of the URI.
2067bc52733SRiver Riddle std::string uriAuthority;
2077bc52733SRiver Riddle if (uri.consume_front("//")) {
2087bc52733SRiver Riddle pos = uri.find('/');
2097bc52733SRiver Riddle uriAuthority = percentDecode(uri.substr(0, pos));
2107bc52733SRiver Riddle uri = uri.substr(pos);
2117bc52733SRiver Riddle }
2127bc52733SRiver Riddle
2137bc52733SRiver Riddle // Decode the body of the URI.
2147bc52733SRiver Riddle std::string uriBody = percentDecode(uri);
2157bc52733SRiver Riddle
2167bc52733SRiver Riddle // Compute the absolute path for this uri.
217f7b8a70eSRiver Riddle if (!getSupportedSchemes().contains(uriScheme)) {
218f7b8a70eSRiver Riddle return llvm::createStringError(llvm::inconvertibleErrorCode(),
219f7b8a70eSRiver Riddle "unsupported URI scheme `" + uriScheme +
220f7b8a70eSRiver Riddle "' for workspace files");
2217bc52733SRiver Riddle }
2227bc52733SRiver Riddle return getAbsolutePath(uriAuthority, uriBody);
2237bc52733SRiver Riddle }
2247bc52733SRiver Riddle
fromURI(StringRef uri)2257bc52733SRiver Riddle llvm::Expected<URIForFile> URIForFile::fromURI(StringRef uri) {
2267bc52733SRiver Riddle llvm::Expected<std::string> filePath = parseFilePathFromURI(uri);
2277bc52733SRiver Riddle if (!filePath)
2287bc52733SRiver Riddle return filePath.takeError();
2297bc52733SRiver Riddle return URIForFile(std::move(*filePath), uri.str());
2307bc52733SRiver Riddle }
2317bc52733SRiver Riddle
fromFile(StringRef absoluteFilepath,StringRef scheme)232f7b8a70eSRiver Riddle llvm::Expected<URIForFile> URIForFile::fromFile(StringRef absoluteFilepath,
233f7b8a70eSRiver Riddle StringRef scheme) {
234f7b8a70eSRiver Riddle llvm::Expected<std::string> uri =
235f7b8a70eSRiver Riddle uriFromAbsolutePath(absoluteFilepath, scheme);
2367bc52733SRiver Riddle if (!uri)
2377bc52733SRiver Riddle return uri.takeError();
2387bc52733SRiver Riddle return fromURI(*uri);
2397bc52733SRiver Riddle }
2407bc52733SRiver Riddle
scheme() const241f7b8a70eSRiver Riddle StringRef URIForFile::scheme() const { return uri().split(':').first; }
242f7b8a70eSRiver Riddle
registerSupportedScheme(StringRef scheme)243f7b8a70eSRiver Riddle void URIForFile::registerSupportedScheme(StringRef scheme) {
244f7b8a70eSRiver Riddle getSupportedSchemes().insert(scheme);
245f7b8a70eSRiver Riddle }
246f7b8a70eSRiver Riddle
fromJSON(const llvm::json::Value & value,URIForFile & result,llvm::json::Path path)2477bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, URIForFile &result,
2487bc52733SRiver Riddle llvm::json::Path path) {
2491da3a795SFangrui Song if (std::optional<StringRef> str = value.getAsString()) {
2507bc52733SRiver Riddle llvm::Expected<URIForFile> expectedURI = URIForFile::fromURI(*str);
2517bc52733SRiver Riddle if (!expectedURI) {
2527bc52733SRiver Riddle path.report("unresolvable URI");
2537bc52733SRiver Riddle consumeError(expectedURI.takeError());
2547bc52733SRiver Riddle return false;
2557bc52733SRiver Riddle }
2567bc52733SRiver Riddle result = std::move(*expectedURI);
2577bc52733SRiver Riddle return true;
2587bc52733SRiver Riddle }
2597bc52733SRiver Riddle return false;
2607bc52733SRiver Riddle }
2617bc52733SRiver Riddle
toJSON(const URIForFile & value)2627bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const URIForFile &value) {
2637bc52733SRiver Riddle return value.uri();
2647bc52733SRiver Riddle }
2657bc52733SRiver Riddle
operator <<(raw_ostream & os,const URIForFile & value)2667bc52733SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os, const URIForFile &value) {
2677bc52733SRiver Riddle return os << value.uri();
2687bc52733SRiver Riddle }
2697bc52733SRiver Riddle
2707bc52733SRiver Riddle //===----------------------------------------------------------------------===//
2717bc52733SRiver Riddle // ClientCapabilities
2727bc52733SRiver Riddle //===----------------------------------------------------------------------===//
2737bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,ClientCapabilities & result,llvm::json::Path path)2747bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
2757bc52733SRiver Riddle ClientCapabilities &result, llvm::json::Path path) {
2767bc52733SRiver Riddle const llvm::json::Object *o = value.getAsObject();
2777bc52733SRiver Riddle if (!o) {
2787bc52733SRiver Riddle path.report("expected object");
2797bc52733SRiver Riddle return false;
2807bc52733SRiver Riddle }
2817bc52733SRiver Riddle if (const llvm::json::Object *textDocument = o->getObject("textDocument")) {
2827bc52733SRiver Riddle if (const llvm::json::Object *documentSymbol =
2837bc52733SRiver Riddle textDocument->getObject("documentSymbol")) {
2841da3a795SFangrui Song if (std::optional<bool> hierarchicalSupport =
2857bc52733SRiver Riddle documentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))
2867bc52733SRiver Riddle result.hierarchicalDocumentSymbol = *hierarchicalSupport;
2877bc52733SRiver Riddle }
288ed344c88SRiver Riddle if (auto *codeAction = textDocument->getObject("codeAction")) {
289ed344c88SRiver Riddle if (codeAction->getObject("codeActionLiteralSupport"))
290ed344c88SRiver Riddle result.codeActionStructure = true;
291ed344c88SRiver Riddle }
2927bc52733SRiver Riddle }
2937bc52733SRiver Riddle return true;
2947bc52733SRiver Riddle }
2957bc52733SRiver Riddle
2967bc52733SRiver Riddle //===----------------------------------------------------------------------===//
297857b0a1fSRiver Riddle // ClientInfo
298857b0a1fSRiver Riddle //===----------------------------------------------------------------------===//
299857b0a1fSRiver Riddle
fromJSON(const llvm::json::Value & value,ClientInfo & result,llvm::json::Path path)300857b0a1fSRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, ClientInfo &result,
301857b0a1fSRiver Riddle llvm::json::Path path) {
302857b0a1fSRiver Riddle llvm::json::ObjectMapper o(value, path);
303857b0a1fSRiver Riddle if (!o || !o.map("name", result.name))
304857b0a1fSRiver Riddle return false;
305857b0a1fSRiver Riddle
306857b0a1fSRiver Riddle // Don't fail if we can't parse version.
307857b0a1fSRiver Riddle o.map("version", result.version);
308857b0a1fSRiver Riddle return true;
309857b0a1fSRiver Riddle }
310857b0a1fSRiver Riddle
311857b0a1fSRiver Riddle //===----------------------------------------------------------------------===//
3127bc52733SRiver Riddle // InitializeParams
3137bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3147bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,TraceLevel & result,llvm::json::Path path)3157bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, TraceLevel &result,
3167bc52733SRiver Riddle llvm::json::Path path) {
3171da3a795SFangrui Song if (std::optional<StringRef> str = value.getAsString()) {
3187bc52733SRiver Riddle if (*str == "off") {
3197bc52733SRiver Riddle result = TraceLevel::Off;
3207bc52733SRiver Riddle return true;
3217bc52733SRiver Riddle }
3227bc52733SRiver Riddle if (*str == "messages") {
3237bc52733SRiver Riddle result = TraceLevel::Messages;
3247bc52733SRiver Riddle return true;
3257bc52733SRiver Riddle }
3267bc52733SRiver Riddle if (*str == "verbose") {
3277bc52733SRiver Riddle result = TraceLevel::Verbose;
3287bc52733SRiver Riddle return true;
3297bc52733SRiver Riddle }
3307bc52733SRiver Riddle }
3317bc52733SRiver Riddle return false;
3327bc52733SRiver Riddle }
3337bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,InitializeParams & result,llvm::json::Path path)3347bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
3357bc52733SRiver Riddle InitializeParams &result, llvm::json::Path path) {
3367bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
3377bc52733SRiver Riddle if (!o)
3387bc52733SRiver Riddle return false;
3397bc52733SRiver Riddle // We deliberately don't fail if we can't parse individual fields.
3407bc52733SRiver Riddle o.map("capabilities", result.capabilities);
3417bc52733SRiver Riddle o.map("trace", result.trace);
342857b0a1fSRiver Riddle mapOptOrNull(value, "clientInfo", result.clientInfo, path);
343857b0a1fSRiver Riddle
3447bc52733SRiver Riddle return true;
3457bc52733SRiver Riddle }
3467bc52733SRiver Riddle
3477bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3487bc52733SRiver Riddle // TextDocumentItem
3497bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3507bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,TextDocumentItem & result,llvm::json::Path path)3517bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
3527bc52733SRiver Riddle TextDocumentItem &result, llvm::json::Path path) {
3537bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
3547bc52733SRiver Riddle return o && o.map("uri", result.uri) &&
3557bc52733SRiver Riddle o.map("languageId", result.languageId) && o.map("text", result.text) &&
3567bc52733SRiver Riddle o.map("version", result.version);
3577bc52733SRiver Riddle }
3587bc52733SRiver Riddle
3597bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3607bc52733SRiver Riddle // TextDocumentIdentifier
3617bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3627bc52733SRiver Riddle
toJSON(const TextDocumentIdentifier & value)3637bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const TextDocumentIdentifier &value) {
3647bc52733SRiver Riddle return llvm::json::Object{{"uri", value.uri}};
3657bc52733SRiver Riddle }
3667bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,TextDocumentIdentifier & result,llvm::json::Path path)3677bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
3687bc52733SRiver Riddle TextDocumentIdentifier &result,
3697bc52733SRiver Riddle llvm::json::Path path) {
3707bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
3717bc52733SRiver Riddle return o && o.map("uri", result.uri);
3727bc52733SRiver Riddle }
3737bc52733SRiver Riddle
3747bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3757bc52733SRiver Riddle // VersionedTextDocumentIdentifier
3767bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3777bc52733SRiver Riddle
3787bc52733SRiver Riddle llvm::json::Value
toJSON(const VersionedTextDocumentIdentifier & value)3797bc52733SRiver Riddle mlir::lsp::toJSON(const VersionedTextDocumentIdentifier &value) {
3807bc52733SRiver Riddle return llvm::json::Object{
3817bc52733SRiver Riddle {"uri", value.uri},
3827bc52733SRiver Riddle {"version", value.version},
3837bc52733SRiver Riddle };
3847bc52733SRiver Riddle }
3857bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,VersionedTextDocumentIdentifier & result,llvm::json::Path path)3867bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
3877bc52733SRiver Riddle VersionedTextDocumentIdentifier &result,
3887bc52733SRiver Riddle llvm::json::Path path) {
3897bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
3907bc52733SRiver Riddle return o && o.map("uri", result.uri) && o.map("version", result.version);
3917bc52733SRiver Riddle }
3927bc52733SRiver Riddle
3937bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3947bc52733SRiver Riddle // Position
3957bc52733SRiver Riddle //===----------------------------------------------------------------------===//
3967bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,Position & result,llvm::json::Path path)3977bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, Position &result,
3987bc52733SRiver Riddle llvm::json::Path path) {
3997bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
4007bc52733SRiver Riddle return o && o.map("line", result.line) &&
4017bc52733SRiver Riddle o.map("character", result.character);
4027bc52733SRiver Riddle }
4037bc52733SRiver Riddle
toJSON(const Position & value)4047bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const Position &value) {
4057bc52733SRiver Riddle return llvm::json::Object{
4067bc52733SRiver Riddle {"line", value.line},
4077bc52733SRiver Riddle {"character", value.character},
4087bc52733SRiver Riddle };
4097bc52733SRiver Riddle }
4107bc52733SRiver Riddle
operator <<(raw_ostream & os,const Position & value)4117bc52733SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os, const Position &value) {
4127bc52733SRiver Riddle return os << value.line << ':' << value.character;
4137bc52733SRiver Riddle }
4147bc52733SRiver Riddle
4157bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4167bc52733SRiver Riddle // Range
4177bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4187bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,Range & result,llvm::json::Path path)4197bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, Range &result,
4207bc52733SRiver Riddle llvm::json::Path path) {
4217bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
4227bc52733SRiver Riddle return o && o.map("start", result.start) && o.map("end", result.end);
4237bc52733SRiver Riddle }
4247bc52733SRiver Riddle
toJSON(const Range & value)4257bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const Range &value) {
4267bc52733SRiver Riddle return llvm::json::Object{
4277bc52733SRiver Riddle {"start", value.start},
4287bc52733SRiver Riddle {"end", value.end},
4297bc52733SRiver Riddle };
4307bc52733SRiver Riddle }
4317bc52733SRiver Riddle
operator <<(raw_ostream & os,const Range & value)4327bc52733SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os, const Range &value) {
4337bc52733SRiver Riddle return os << value.start << '-' << value.end;
4347bc52733SRiver Riddle }
4357bc52733SRiver Riddle
4367bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4377bc52733SRiver Riddle // Location
4387bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4397bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,Location & result,llvm::json::Path path)440ed344c88SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, Location &result,
441ed344c88SRiver Riddle llvm::json::Path path) {
442ed344c88SRiver Riddle llvm::json::ObjectMapper o(value, path);
443ed344c88SRiver Riddle return o && o.map("uri", result.uri) && o.map("range", result.range);
444ed344c88SRiver Riddle }
445ed344c88SRiver Riddle
toJSON(const Location & value)4467bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const Location &value) {
4477bc52733SRiver Riddle return llvm::json::Object{
4487bc52733SRiver Riddle {"uri", value.uri},
4497bc52733SRiver Riddle {"range", value.range},
4507bc52733SRiver Riddle };
4517bc52733SRiver Riddle }
4527bc52733SRiver Riddle
operator <<(raw_ostream & os,const Location & value)4537bc52733SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os, const Location &value) {
4547bc52733SRiver Riddle return os << value.range << '@' << value.uri;
4557bc52733SRiver Riddle }
4567bc52733SRiver Riddle
4577bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4587bc52733SRiver Riddle // TextDocumentPositionParams
4597bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4607bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,TextDocumentPositionParams & result,llvm::json::Path path)4617bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
4627bc52733SRiver Riddle TextDocumentPositionParams &result,
4637bc52733SRiver Riddle llvm::json::Path path) {
4647bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
4657bc52733SRiver Riddle return o && o.map("textDocument", result.textDocument) &&
4667bc52733SRiver Riddle o.map("position", result.position);
4677bc52733SRiver Riddle }
4687bc52733SRiver Riddle
4697bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4707bc52733SRiver Riddle // ReferenceParams
4717bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4727bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,ReferenceContext & result,llvm::json::Path path)4737bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
4747bc52733SRiver Riddle ReferenceContext &result, llvm::json::Path path) {
4757bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
4767bc52733SRiver Riddle return o && o.mapOptional("includeDeclaration", result.includeDeclaration);
4777bc52733SRiver Riddle }
4787bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,ReferenceParams & result,llvm::json::Path path)4797bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
4807bc52733SRiver Riddle ReferenceParams &result, llvm::json::Path path) {
4817bc52733SRiver Riddle TextDocumentPositionParams &base = result;
4827bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
4837bc52733SRiver Riddle return fromJSON(value, base, path) && o &&
4847bc52733SRiver Riddle o.mapOptional("context", result.context);
4857bc52733SRiver Riddle }
4867bc52733SRiver Riddle
4877bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4887bc52733SRiver Riddle // DidOpenTextDocumentParams
4897bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4907bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,DidOpenTextDocumentParams & result,llvm::json::Path path)4917bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
4927bc52733SRiver Riddle DidOpenTextDocumentParams &result,
4937bc52733SRiver Riddle llvm::json::Path path) {
4947bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
4957bc52733SRiver Riddle return o && o.map("textDocument", result.textDocument);
4967bc52733SRiver Riddle }
4977bc52733SRiver Riddle
4987bc52733SRiver Riddle //===----------------------------------------------------------------------===//
4997bc52733SRiver Riddle // DidCloseTextDocumentParams
5007bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5017bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,DidCloseTextDocumentParams & result,llvm::json::Path path)5027bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
5037bc52733SRiver Riddle DidCloseTextDocumentParams &result,
5047bc52733SRiver Riddle llvm::json::Path path) {
5057bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
5067bc52733SRiver Riddle return o && o.map("textDocument", result.textDocument);
5077bc52733SRiver Riddle }
5087bc52733SRiver Riddle
5097bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5107bc52733SRiver Riddle // DidChangeTextDocumentParams
5117bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5127bc52733SRiver Riddle
5136187178eSRiver Riddle LogicalResult
applyTo(std::string & contents) const5146187178eSRiver Riddle TextDocumentContentChangeEvent::applyTo(std::string &contents) const {
5156187178eSRiver Riddle // If there is no range, the full document changed.
5166187178eSRiver Riddle if (!range) {
5176187178eSRiver Riddle contents = text;
5186187178eSRiver Riddle return success();
5196187178eSRiver Riddle }
5206187178eSRiver Riddle
5216187178eSRiver Riddle // Try to map the replacement range to the content.
5226187178eSRiver Riddle llvm::SourceMgr tmpScrMgr;
5236187178eSRiver Riddle tmpScrMgr.AddNewSourceBuffer(llvm::MemoryBuffer::getMemBuffer(contents),
5246187178eSRiver Riddle SMLoc());
5256187178eSRiver Riddle SMRange rangeLoc = range->getAsSMRange(tmpScrMgr);
5266187178eSRiver Riddle if (!rangeLoc.isValid())
5276187178eSRiver Riddle return failure();
5286187178eSRiver Riddle
5296187178eSRiver Riddle contents.replace(rangeLoc.Start.getPointer() - contents.data(),
5306187178eSRiver Riddle rangeLoc.End.getPointer() - rangeLoc.Start.getPointer(),
5316187178eSRiver Riddle text);
5326187178eSRiver Riddle return success();
5336187178eSRiver Riddle }
5346187178eSRiver Riddle
applyTo(ArrayRef<TextDocumentContentChangeEvent> changes,std::string & contents)5356187178eSRiver Riddle LogicalResult TextDocumentContentChangeEvent::applyTo(
5366187178eSRiver Riddle ArrayRef<TextDocumentContentChangeEvent> changes, std::string &contents) {
5376187178eSRiver Riddle for (const auto &change : changes)
5386187178eSRiver Riddle if (failed(change.applyTo(contents)))
5396187178eSRiver Riddle return failure();
5406187178eSRiver Riddle return success();
5416187178eSRiver Riddle }
5426187178eSRiver Riddle
fromJSON(const llvm::json::Value & value,TextDocumentContentChangeEvent & result,llvm::json::Path path)5437bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
5447bc52733SRiver Riddle TextDocumentContentChangeEvent &result,
5457bc52733SRiver Riddle llvm::json::Path path) {
5467bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
5477bc52733SRiver Riddle return o && o.map("range", result.range) &&
5487bc52733SRiver Riddle o.map("rangeLength", result.rangeLength) && o.map("text", result.text);
5497bc52733SRiver Riddle }
5507bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,DidChangeTextDocumentParams & result,llvm::json::Path path)5517bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
5527bc52733SRiver Riddle DidChangeTextDocumentParams &result,
5537bc52733SRiver Riddle llvm::json::Path path) {
5547bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
5557bc52733SRiver Riddle return o && o.map("textDocument", result.textDocument) &&
5567bc52733SRiver Riddle o.map("contentChanges", result.contentChanges);
5577bc52733SRiver Riddle }
5587bc52733SRiver Riddle
5597bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5607bc52733SRiver Riddle // MarkupContent
5617bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5627bc52733SRiver Riddle
toTextKind(MarkupKind kind)5637bc52733SRiver Riddle static llvm::StringRef toTextKind(MarkupKind kind) {
5647bc52733SRiver Riddle switch (kind) {
5657bc52733SRiver Riddle case MarkupKind::PlainText:
5667bc52733SRiver Riddle return "plaintext";
5677bc52733SRiver Riddle case MarkupKind::Markdown:
5687bc52733SRiver Riddle return "markdown";
5697bc52733SRiver Riddle }
5707bc52733SRiver Riddle llvm_unreachable("Invalid MarkupKind");
5717bc52733SRiver Riddle }
5727bc52733SRiver Riddle
operator <<(raw_ostream & os,MarkupKind kind)5737bc52733SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os, MarkupKind kind) {
5747bc52733SRiver Riddle return os << toTextKind(kind);
5757bc52733SRiver Riddle }
5767bc52733SRiver Riddle
toJSON(const MarkupContent & mc)5777bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const MarkupContent &mc) {
5787bc52733SRiver Riddle if (mc.value.empty())
5797bc52733SRiver Riddle return nullptr;
5807bc52733SRiver Riddle
5817bc52733SRiver Riddle return llvm::json::Object{
5827bc52733SRiver Riddle {"kind", toTextKind(mc.kind)},
5837bc52733SRiver Riddle {"value", mc.value},
5847bc52733SRiver Riddle };
5857bc52733SRiver Riddle }
5867bc52733SRiver Riddle
5877bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5887bc52733SRiver Riddle // Hover
5897bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5907bc52733SRiver Riddle
toJSON(const Hover & hover)5917bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const Hover &hover) {
5927bc52733SRiver Riddle llvm::json::Object result{{"contents", toJSON(hover.contents)}};
593037f0995SKazu Hirata if (hover.range)
5947bc52733SRiver Riddle result["range"] = toJSON(*hover.range);
5957bc52733SRiver Riddle return std::move(result);
5967bc52733SRiver Riddle }
5977bc52733SRiver Riddle
5987bc52733SRiver Riddle //===----------------------------------------------------------------------===//
5997bc52733SRiver Riddle // DocumentSymbol
6007bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6017bc52733SRiver Riddle
toJSON(const DocumentSymbol & symbol)6027bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const DocumentSymbol &symbol) {
6037bc52733SRiver Riddle llvm::json::Object result{{"name", symbol.name},
6047bc52733SRiver Riddle {"kind", static_cast<int>(symbol.kind)},
6057bc52733SRiver Riddle {"range", symbol.range},
6067bc52733SRiver Riddle {"selectionRange", symbol.selectionRange}};
6077bc52733SRiver Riddle
6087bc52733SRiver Riddle if (!symbol.detail.empty())
6097bc52733SRiver Riddle result["detail"] = symbol.detail;
6107bc52733SRiver Riddle if (!symbol.children.empty())
6117bc52733SRiver Riddle result["children"] = symbol.children;
6127bc52733SRiver Riddle return std::move(result);
6137bc52733SRiver Riddle }
6147bc52733SRiver Riddle
6157bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6167bc52733SRiver Riddle // DocumentSymbolParams
6177bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6187bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,DocumentSymbolParams & result,llvm::json::Path path)6197bc52733SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
6207bc52733SRiver Riddle DocumentSymbolParams &result, llvm::json::Path path) {
6217bc52733SRiver Riddle llvm::json::ObjectMapper o(value, path);
6227bc52733SRiver Riddle return o && o.map("textDocument", result.textDocument);
6237bc52733SRiver Riddle }
6247bc52733SRiver Riddle
6257bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6267bc52733SRiver Riddle // DiagnosticRelatedInformation
6277bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6287bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,DiagnosticRelatedInformation & result,llvm::json::Path path)629ed344c88SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
630ed344c88SRiver Riddle DiagnosticRelatedInformation &result,
631ed344c88SRiver Riddle llvm::json::Path path) {
632ed344c88SRiver Riddle llvm::json::ObjectMapper o(value, path);
633ed344c88SRiver Riddle return o && o.map("location", result.location) &&
634ed344c88SRiver Riddle o.map("message", result.message);
635ed344c88SRiver Riddle }
636ed344c88SRiver Riddle
toJSON(const DiagnosticRelatedInformation & info)6377bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const DiagnosticRelatedInformation &info) {
6387bc52733SRiver Riddle return llvm::json::Object{
6397bc52733SRiver Riddle {"location", info.location},
6407bc52733SRiver Riddle {"message", info.message},
6417bc52733SRiver Riddle };
6427bc52733SRiver Riddle }
6437bc52733SRiver Riddle
6447bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6457bc52733SRiver Riddle // Diagnostic
6467bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6477bc52733SRiver Riddle
toJSON(DiagnosticTag tag)648*878c141aSLily Brown llvm::json::Value mlir::lsp::toJSON(DiagnosticTag tag) {
649*878c141aSLily Brown return static_cast<int>(tag);
650*878c141aSLily Brown }
651*878c141aSLily Brown
fromJSON(const llvm::json::Value & value,DiagnosticTag & result,llvm::json::Path path)652*878c141aSLily Brown bool mlir::lsp::fromJSON(const llvm::json::Value &value, DiagnosticTag &result,
653*878c141aSLily Brown llvm::json::Path path) {
654*878c141aSLily Brown if (std::optional<int64_t> i = value.getAsInteger()) {
655*878c141aSLily Brown result = (DiagnosticTag)*i;
656*878c141aSLily Brown return true;
657*878c141aSLily Brown }
658*878c141aSLily Brown
659*878c141aSLily Brown return false;
660*878c141aSLily Brown }
661*878c141aSLily Brown
toJSON(const Diagnostic & diag)6627bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const Diagnostic &diag) {
6637bc52733SRiver Riddle llvm::json::Object result{
6647bc52733SRiver Riddle {"range", diag.range},
6657bc52733SRiver Riddle {"severity", (int)diag.severity},
6667bc52733SRiver Riddle {"message", diag.message},
6677bc52733SRiver Riddle };
6687bc52733SRiver Riddle if (diag.category)
6697bc52733SRiver Riddle result["category"] = *diag.category;
6707bc52733SRiver Riddle if (!diag.source.empty())
6717bc52733SRiver Riddle result["source"] = diag.source;
6727bc52733SRiver Riddle if (diag.relatedInformation)
6737bc52733SRiver Riddle result["relatedInformation"] = *diag.relatedInformation;
674*878c141aSLily Brown if (!diag.tags.empty())
675*878c141aSLily Brown result["tags"] = diag.tags;
6767bc52733SRiver Riddle return std::move(result);
6777bc52733SRiver Riddle }
6787bc52733SRiver Riddle
fromJSON(const llvm::json::Value & value,Diagnostic & result,llvm::json::Path path)679ed344c88SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, Diagnostic &result,
680ed344c88SRiver Riddle llvm::json::Path path) {
681ed344c88SRiver Riddle llvm::json::ObjectMapper o(value, path);
682ed344c88SRiver Riddle if (!o)
683ed344c88SRiver Riddle return false;
684ed344c88SRiver Riddle int severity = 0;
685ed344c88SRiver Riddle if (!mapOptOrNull(value, "severity", severity, path))
686ed344c88SRiver Riddle return false;
687ed344c88SRiver Riddle result.severity = (DiagnosticSeverity)severity;
688ed344c88SRiver Riddle
689ed344c88SRiver Riddle return o.map("range", result.range) && o.map("message", result.message) &&
690ed344c88SRiver Riddle mapOptOrNull(value, "category", result.category, path) &&
691ed344c88SRiver Riddle mapOptOrNull(value, "source", result.source, path) &&
692ed344c88SRiver Riddle mapOptOrNull(value, "relatedInformation", result.relatedInformation,
693*878c141aSLily Brown path) &&
694*878c141aSLily Brown mapOptOrNull(value, "tags", result.tags, path);
695ed344c88SRiver Riddle }
696ed344c88SRiver Riddle
6977bc52733SRiver Riddle //===----------------------------------------------------------------------===//
6987bc52733SRiver Riddle // PublishDiagnosticsParams
6997bc52733SRiver Riddle //===----------------------------------------------------------------------===//
7007bc52733SRiver Riddle
toJSON(const PublishDiagnosticsParams & params)7017bc52733SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const PublishDiagnosticsParams ¶ms) {
7027bc52733SRiver Riddle return llvm::json::Object{
7037bc52733SRiver Riddle {"uri", params.uri},
7047bc52733SRiver Riddle {"diagnostics", params.diagnostics},
7057bc52733SRiver Riddle {"version", params.version},
7067bc52733SRiver Riddle };
7077bc52733SRiver Riddle }
708008de486SRiver Riddle
709008de486SRiver Riddle //===----------------------------------------------------------------------===//
710008de486SRiver Riddle // TextEdit
711008de486SRiver Riddle //===----------------------------------------------------------------------===//
712008de486SRiver Riddle
fromJSON(const llvm::json::Value & value,TextEdit & result,llvm::json::Path path)713008de486SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, TextEdit &result,
714008de486SRiver Riddle llvm::json::Path path) {
715008de486SRiver Riddle llvm::json::ObjectMapper o(value, path);
716008de486SRiver Riddle return o && o.map("range", result.range) && o.map("newText", result.newText);
717008de486SRiver Riddle }
718008de486SRiver Riddle
toJSON(const TextEdit & value)719008de486SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const TextEdit &value) {
720008de486SRiver Riddle return llvm::json::Object{
721008de486SRiver Riddle {"range", value.range},
722008de486SRiver Riddle {"newText", value.newText},
723008de486SRiver Riddle };
724008de486SRiver Riddle }
725008de486SRiver Riddle
operator <<(raw_ostream & os,const TextEdit & value)726008de486SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os, const TextEdit &value) {
727008de486SRiver Riddle os << value.range << " => \"";
728008de486SRiver Riddle llvm::printEscapedString(value.newText, os);
729008de486SRiver Riddle return os << '"';
730008de486SRiver Riddle }
731008de486SRiver Riddle
732008de486SRiver Riddle //===----------------------------------------------------------------------===//
733008de486SRiver Riddle // CompletionItemKind
734008de486SRiver Riddle //===----------------------------------------------------------------------===//
735008de486SRiver Riddle
fromJSON(const llvm::json::Value & value,CompletionItemKind & result,llvm::json::Path path)736008de486SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
737008de486SRiver Riddle CompletionItemKind &result, llvm::json::Path path) {
7381da3a795SFangrui Song if (std::optional<int64_t> intValue = value.getAsInteger()) {
739008de486SRiver Riddle if (*intValue < static_cast<int>(CompletionItemKind::Text) ||
740008de486SRiver Riddle *intValue > static_cast<int>(CompletionItemKind::TypeParameter))
741008de486SRiver Riddle return false;
742008de486SRiver Riddle result = static_cast<CompletionItemKind>(*intValue);
743008de486SRiver Riddle return true;
744008de486SRiver Riddle }
745008de486SRiver Riddle return false;
746008de486SRiver Riddle }
747008de486SRiver Riddle
adjustKindToCapability(CompletionItemKind kind,CompletionItemKindBitset & supportedCompletionItemKinds)748008de486SRiver Riddle CompletionItemKind mlir::lsp::adjustKindToCapability(
749008de486SRiver Riddle CompletionItemKind kind,
750008de486SRiver Riddle CompletionItemKindBitset &supportedCompletionItemKinds) {
751008de486SRiver Riddle size_t kindVal = static_cast<size_t>(kind);
752008de486SRiver Riddle if (kindVal >= kCompletionItemKindMin &&
753008de486SRiver Riddle kindVal <= supportedCompletionItemKinds.size() &&
754008de486SRiver Riddle supportedCompletionItemKinds[kindVal])
755008de486SRiver Riddle return kind;
756008de486SRiver Riddle
757008de486SRiver Riddle // Provide some fall backs for common kinds that are close enough.
758008de486SRiver Riddle switch (kind) {
759008de486SRiver Riddle case CompletionItemKind::Folder:
760008de486SRiver Riddle return CompletionItemKind::File;
761008de486SRiver Riddle case CompletionItemKind::EnumMember:
762008de486SRiver Riddle return CompletionItemKind::Enum;
763008de486SRiver Riddle case CompletionItemKind::Struct:
764008de486SRiver Riddle return CompletionItemKind::Class;
765008de486SRiver Riddle default:
766008de486SRiver Riddle return CompletionItemKind::Text;
767008de486SRiver Riddle }
768008de486SRiver Riddle }
769008de486SRiver Riddle
fromJSON(const llvm::json::Value & value,CompletionItemKindBitset & result,llvm::json::Path path)770008de486SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
771008de486SRiver Riddle CompletionItemKindBitset &result,
772008de486SRiver Riddle llvm::json::Path path) {
773008de486SRiver Riddle if (const llvm::json::Array *arrayValue = value.getAsArray()) {
774008de486SRiver Riddle for (size_t i = 0, e = arrayValue->size(); i < e; ++i) {
775008de486SRiver Riddle CompletionItemKind kindOut;
776008de486SRiver Riddle if (fromJSON((*arrayValue)[i], kindOut, path.index(i)))
777008de486SRiver Riddle result.set(size_t(kindOut));
778008de486SRiver Riddle }
779008de486SRiver Riddle return true;
780008de486SRiver Riddle }
781008de486SRiver Riddle return false;
782008de486SRiver Riddle }
783008de486SRiver Riddle
784008de486SRiver Riddle //===----------------------------------------------------------------------===//
785008de486SRiver Riddle // CompletionItem
786008de486SRiver Riddle //===----------------------------------------------------------------------===//
787008de486SRiver Riddle
toJSON(const CompletionItem & value)788008de486SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const CompletionItem &value) {
789008de486SRiver Riddle assert(!value.label.empty() && "completion item label is required");
790008de486SRiver Riddle llvm::json::Object result{{"label", value.label}};
791008de486SRiver Riddle if (value.kind != CompletionItemKind::Missing)
792008de486SRiver Riddle result["kind"] = static_cast<int>(value.kind);
793008de486SRiver Riddle if (!value.detail.empty())
794008de486SRiver Riddle result["detail"] = value.detail;
795008de486SRiver Riddle if (value.documentation)
796008de486SRiver Riddle result["documentation"] = value.documentation;
797008de486SRiver Riddle if (!value.sortText.empty())
798008de486SRiver Riddle result["sortText"] = value.sortText;
799008de486SRiver Riddle if (!value.filterText.empty())
800008de486SRiver Riddle result["filterText"] = value.filterText;
801008de486SRiver Riddle if (!value.insertText.empty())
802008de486SRiver Riddle result["insertText"] = value.insertText;
803008de486SRiver Riddle if (value.insertTextFormat != InsertTextFormat::Missing)
804008de486SRiver Riddle result["insertTextFormat"] = static_cast<int>(value.insertTextFormat);
805008de486SRiver Riddle if (value.textEdit)
806008de486SRiver Riddle result["textEdit"] = *value.textEdit;
807008de486SRiver Riddle if (!value.additionalTextEdits.empty()) {
808008de486SRiver Riddle result["additionalTextEdits"] =
809008de486SRiver Riddle llvm::json::Array(value.additionalTextEdits);
810008de486SRiver Riddle }
811008de486SRiver Riddle if (value.deprecated)
812008de486SRiver Riddle result["deprecated"] = value.deprecated;
813008de486SRiver Riddle return std::move(result);
814008de486SRiver Riddle }
815008de486SRiver Riddle
operator <<(raw_ostream & os,const CompletionItem & value)816008de486SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os,
817008de486SRiver Riddle const CompletionItem &value) {
818008de486SRiver Riddle return os << value.label << " - " << toJSON(value);
819008de486SRiver Riddle }
820008de486SRiver Riddle
operator <(const CompletionItem & lhs,const CompletionItem & rhs)821008de486SRiver Riddle bool mlir::lsp::operator<(const CompletionItem &lhs,
822008de486SRiver Riddle const CompletionItem &rhs) {
823008de486SRiver Riddle return (lhs.sortText.empty() ? lhs.label : lhs.sortText) <
824008de486SRiver Riddle (rhs.sortText.empty() ? rhs.label : rhs.sortText);
825008de486SRiver Riddle }
826008de486SRiver Riddle
827008de486SRiver Riddle //===----------------------------------------------------------------------===//
828008de486SRiver Riddle // CompletionList
829008de486SRiver Riddle //===----------------------------------------------------------------------===//
830008de486SRiver Riddle
toJSON(const CompletionList & value)831008de486SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const CompletionList &value) {
832008de486SRiver Riddle return llvm::json::Object{
833008de486SRiver Riddle {"isIncomplete", value.isIncomplete},
834008de486SRiver Riddle {"items", llvm::json::Array(value.items)},
835008de486SRiver Riddle };
836008de486SRiver Riddle }
837008de486SRiver Riddle
838008de486SRiver Riddle //===----------------------------------------------------------------------===//
839008de486SRiver Riddle // CompletionContext
840008de486SRiver Riddle //===----------------------------------------------------------------------===//
841008de486SRiver Riddle
fromJSON(const llvm::json::Value & value,CompletionContext & result,llvm::json::Path path)842008de486SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
843008de486SRiver Riddle CompletionContext &result, llvm::json::Path path) {
844008de486SRiver Riddle llvm::json::ObjectMapper o(value, path);
845008de486SRiver Riddle int triggerKind;
846008de486SRiver Riddle if (!o || !o.map("triggerKind", triggerKind) ||
847008de486SRiver Riddle !mapOptOrNull(value, "triggerCharacter", result.triggerCharacter, path))
848008de486SRiver Riddle return false;
849008de486SRiver Riddle result.triggerKind = static_cast<CompletionTriggerKind>(triggerKind);
850008de486SRiver Riddle return true;
851008de486SRiver Riddle }
852008de486SRiver Riddle
853008de486SRiver Riddle //===----------------------------------------------------------------------===//
854008de486SRiver Riddle // CompletionParams
855008de486SRiver Riddle //===----------------------------------------------------------------------===//
856008de486SRiver Riddle
fromJSON(const llvm::json::Value & value,CompletionParams & result,llvm::json::Path path)857008de486SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
858008de486SRiver Riddle CompletionParams &result, llvm::json::Path path) {
859008de486SRiver Riddle if (!fromJSON(value, static_cast<TextDocumentPositionParams &>(result), path))
860008de486SRiver Riddle return false;
861008de486SRiver Riddle if (const llvm::json::Value *context = value.getAsObject()->get("context"))
862008de486SRiver Riddle return fromJSON(*context, result.context, path.field("context"));
863008de486SRiver Riddle return true;
864008de486SRiver Riddle }
865469c5894SRiver Riddle
866469c5894SRiver Riddle //===----------------------------------------------------------------------===//
867469c5894SRiver Riddle // ParameterInformation
868469c5894SRiver Riddle //===----------------------------------------------------------------------===//
869469c5894SRiver Riddle
toJSON(const ParameterInformation & value)870469c5894SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const ParameterInformation &value) {
8715413bf1bSKazu Hirata assert((value.labelOffsets || !value.labelString.empty()) &&
872469c5894SRiver Riddle "parameter information label is required");
873469c5894SRiver Riddle llvm::json::Object result;
874469c5894SRiver Riddle if (value.labelOffsets)
875469c5894SRiver Riddle result["label"] = llvm::json::Array(
876469c5894SRiver Riddle {value.labelOffsets->first, value.labelOffsets->second});
877469c5894SRiver Riddle else
878469c5894SRiver Riddle result["label"] = value.labelString;
879469c5894SRiver Riddle if (!value.documentation.empty())
880469c5894SRiver Riddle result["documentation"] = value.documentation;
881469c5894SRiver Riddle return std::move(result);
882469c5894SRiver Riddle }
883469c5894SRiver Riddle
884469c5894SRiver Riddle //===----------------------------------------------------------------------===//
885469c5894SRiver Riddle // SignatureInformation
886469c5894SRiver Riddle //===----------------------------------------------------------------------===//
887469c5894SRiver Riddle
toJSON(const SignatureInformation & value)888469c5894SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const SignatureInformation &value) {
889469c5894SRiver Riddle assert(!value.label.empty() && "signature information label is required");
890469c5894SRiver Riddle llvm::json::Object result{
891469c5894SRiver Riddle {"label", value.label},
892469c5894SRiver Riddle {"parameters", llvm::json::Array(value.parameters)},
893469c5894SRiver Riddle };
894469c5894SRiver Riddle if (!value.documentation.empty())
895469c5894SRiver Riddle result["documentation"] = value.documentation;
896469c5894SRiver Riddle return std::move(result);
897469c5894SRiver Riddle }
898469c5894SRiver Riddle
operator <<(raw_ostream & os,const SignatureInformation & value)899469c5894SRiver Riddle raw_ostream &mlir::lsp::operator<<(raw_ostream &os,
900469c5894SRiver Riddle const SignatureInformation &value) {
901469c5894SRiver Riddle return os << value.label << " - " << toJSON(value);
902469c5894SRiver Riddle }
903469c5894SRiver Riddle
904469c5894SRiver Riddle //===----------------------------------------------------------------------===//
905469c5894SRiver Riddle // SignatureHelp
906469c5894SRiver Riddle //===----------------------------------------------------------------------===//
907469c5894SRiver Riddle
toJSON(const SignatureHelp & value)908469c5894SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const SignatureHelp &value) {
909469c5894SRiver Riddle assert(value.activeSignature >= 0 &&
910469c5894SRiver Riddle "Unexpected negative value for number of active signatures.");
911469c5894SRiver Riddle assert(value.activeParameter >= 0 &&
912469c5894SRiver Riddle "Unexpected negative value for active parameter index");
913469c5894SRiver Riddle return llvm::json::Object{
914469c5894SRiver Riddle {"activeSignature", value.activeSignature},
915469c5894SRiver Riddle {"activeParameter", value.activeParameter},
916469c5894SRiver Riddle {"signatures", llvm::json::Array(value.signatures)},
917469c5894SRiver Riddle };
918469c5894SRiver Riddle }
91909af7fefSRiver Riddle
92009af7fefSRiver Riddle //===----------------------------------------------------------------------===//
92109af7fefSRiver Riddle // DocumentLinkParams
92209af7fefSRiver Riddle //===----------------------------------------------------------------------===//
92309af7fefSRiver Riddle
fromJSON(const llvm::json::Value & value,DocumentLinkParams & result,llvm::json::Path path)92409af7fefSRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
92509af7fefSRiver Riddle DocumentLinkParams &result, llvm::json::Path path) {
92609af7fefSRiver Riddle llvm::json::ObjectMapper o(value, path);
92709af7fefSRiver Riddle return o && o.map("textDocument", result.textDocument);
92809af7fefSRiver Riddle }
92909af7fefSRiver Riddle
93009af7fefSRiver Riddle //===----------------------------------------------------------------------===//
93109af7fefSRiver Riddle // DocumentLink
93209af7fefSRiver Riddle //===----------------------------------------------------------------------===//
93309af7fefSRiver Riddle
toJSON(const DocumentLink & value)93409af7fefSRiver Riddle llvm::json::Value mlir::lsp::toJSON(const DocumentLink &value) {
93509af7fefSRiver Riddle return llvm::json::Object{
93609af7fefSRiver Riddle {"range", value.range},
93709af7fefSRiver Riddle {"target", value.target},
93809af7fefSRiver Riddle };
93909af7fefSRiver Riddle }
9405919eab5SRiver Riddle
9415919eab5SRiver Riddle //===----------------------------------------------------------------------===//
9425919eab5SRiver Riddle // InlayHintsParams
9435919eab5SRiver Riddle //===----------------------------------------------------------------------===//
9445919eab5SRiver Riddle
fromJSON(const llvm::json::Value & value,InlayHintsParams & result,llvm::json::Path path)9455919eab5SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
9465919eab5SRiver Riddle InlayHintsParams &result, llvm::json::Path path) {
9475919eab5SRiver Riddle llvm::json::ObjectMapper o(value, path);
9485919eab5SRiver Riddle return o && o.map("textDocument", result.textDocument) &&
9495919eab5SRiver Riddle o.map("range", result.range);
9505919eab5SRiver Riddle }
9515919eab5SRiver Riddle
9525919eab5SRiver Riddle //===----------------------------------------------------------------------===//
9535919eab5SRiver Riddle // InlayHint
9545919eab5SRiver Riddle //===----------------------------------------------------------------------===//
9555919eab5SRiver Riddle
toJSON(const InlayHint & value)9565919eab5SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const InlayHint &value) {
9575919eab5SRiver Riddle return llvm::json::Object{{"position", value.position},
9585919eab5SRiver Riddle {"kind", (int)value.kind},
9595919eab5SRiver Riddle {"label", value.label},
9605919eab5SRiver Riddle {"paddingLeft", value.paddingLeft},
9615919eab5SRiver Riddle {"paddingRight", value.paddingRight}};
9625919eab5SRiver Riddle }
operator ==(const InlayHint & lhs,const InlayHint & rhs)9635919eab5SRiver Riddle bool mlir::lsp::operator==(const InlayHint &lhs, const InlayHint &rhs) {
9645919eab5SRiver Riddle return std::tie(lhs.position, lhs.kind, lhs.label) ==
9655919eab5SRiver Riddle std::tie(rhs.position, rhs.kind, rhs.label);
9665919eab5SRiver Riddle }
operator <(const InlayHint & lhs,const InlayHint & rhs)9675919eab5SRiver Riddle bool mlir::lsp::operator<(const InlayHint &lhs, const InlayHint &rhs) {
9685919eab5SRiver Riddle return std::tie(lhs.position, lhs.kind, lhs.label) <
9695919eab5SRiver Riddle std::tie(rhs.position, rhs.kind, rhs.label);
9705919eab5SRiver Riddle }
9715919eab5SRiver Riddle
operator <<(llvm::raw_ostream & os,InlayHintKind value)9725919eab5SRiver Riddle llvm::raw_ostream &mlir::lsp::operator<<(llvm::raw_ostream &os,
9735919eab5SRiver Riddle InlayHintKind value) {
9745919eab5SRiver Riddle switch (value) {
9755919eab5SRiver Riddle case InlayHintKind::Parameter:
9765919eab5SRiver Riddle return os << "parameter";
9775919eab5SRiver Riddle case InlayHintKind::Type:
9785919eab5SRiver Riddle return os << "type";
9795919eab5SRiver Riddle }
9805919eab5SRiver Riddle llvm_unreachable("Unknown InlayHintKind");
9815919eab5SRiver Riddle }
982ed344c88SRiver Riddle
983ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
984ed344c88SRiver Riddle // CodeActionContext
985ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
986ed344c88SRiver Riddle
fromJSON(const llvm::json::Value & value,CodeActionContext & result,llvm::json::Path path)987ed344c88SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
988ed344c88SRiver Riddle CodeActionContext &result, llvm::json::Path path) {
989ed344c88SRiver Riddle llvm::json::ObjectMapper o(value, path);
990ed344c88SRiver Riddle if (!o || !o.map("diagnostics", result.diagnostics))
991ed344c88SRiver Riddle return false;
992ed344c88SRiver Riddle o.map("only", result.only);
993ed344c88SRiver Riddle return true;
994ed344c88SRiver Riddle }
995ed344c88SRiver Riddle
996ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
997ed344c88SRiver Riddle // CodeActionParams
998ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
999ed344c88SRiver Riddle
fromJSON(const llvm::json::Value & value,CodeActionParams & result,llvm::json::Path path)1000ed344c88SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value,
1001ed344c88SRiver Riddle CodeActionParams &result, llvm::json::Path path) {
1002ed344c88SRiver Riddle llvm::json::ObjectMapper o(value, path);
1003ed344c88SRiver Riddle return o && o.map("textDocument", result.textDocument) &&
1004ed344c88SRiver Riddle o.map("range", result.range) && o.map("context", result.context);
1005ed344c88SRiver Riddle }
1006ed344c88SRiver Riddle
1007ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
1008ed344c88SRiver Riddle // WorkspaceEdit
1009ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
1010ed344c88SRiver Riddle
fromJSON(const llvm::json::Value & value,WorkspaceEdit & result,llvm::json::Path path)1011ed344c88SRiver Riddle bool mlir::lsp::fromJSON(const llvm::json::Value &value, WorkspaceEdit &result,
1012ed344c88SRiver Riddle llvm::json::Path path) {
1013ed344c88SRiver Riddle llvm::json::ObjectMapper o(value, path);
1014ed344c88SRiver Riddle return o && o.map("changes", result.changes);
1015ed344c88SRiver Riddle }
1016ed344c88SRiver Riddle
toJSON(const WorkspaceEdit & value)1017ed344c88SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const WorkspaceEdit &value) {
1018ed344c88SRiver Riddle llvm::json::Object fileChanges;
1019ed344c88SRiver Riddle for (auto &change : value.changes)
1020ed344c88SRiver Riddle fileChanges[change.first] = llvm::json::Array(change.second);
1021ed344c88SRiver Riddle return llvm::json::Object{{"changes", std::move(fileChanges)}};
1022ed344c88SRiver Riddle }
1023ed344c88SRiver Riddle
1024ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
1025ed344c88SRiver Riddle // CodeAction
1026ed344c88SRiver Riddle //===----------------------------------------------------------------------===//
1027ed344c88SRiver Riddle
1028ed344c88SRiver Riddle const llvm::StringLiteral CodeAction::kQuickFix = "quickfix";
1029ed344c88SRiver Riddle const llvm::StringLiteral CodeAction::kRefactor = "refactor";
1030ed344c88SRiver Riddle const llvm::StringLiteral CodeAction::kInfo = "info";
1031ed344c88SRiver Riddle
toJSON(const CodeAction & value)1032ed344c88SRiver Riddle llvm::json::Value mlir::lsp::toJSON(const CodeAction &value) {
1033ed344c88SRiver Riddle llvm::json::Object codeAction{{"title", value.title}};
1034ed344c88SRiver Riddle if (value.kind)
1035ed344c88SRiver Riddle codeAction["kind"] = *value.kind;
1036ed344c88SRiver Riddle if (value.diagnostics)
1037ed344c88SRiver Riddle codeAction["diagnostics"] = llvm::json::Array(*value.diagnostics);
1038ed344c88SRiver Riddle if (value.isPreferred)
1039ed344c88SRiver Riddle codeAction["isPreferred"] = true;
1040ed344c88SRiver Riddle if (value.edit)
1041ed344c88SRiver Riddle codeAction["edit"] = *value.edit;
1042ed344c88SRiver Riddle return std::move(codeAction);
1043ed344c88SRiver Riddle }
1044