diff options
| author | Yong He <yonghe@outlook.com> | 2024-10-27 14:27:52 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-27 14:27:52 -0700 |
| commit | 1dd6ec26776081274604a94a96a1d87818830e82 (patch) | |
| tree | 25b3a7d2df98cc152986b04725f61e69e1492b3a /source/slang/slang-language-server.cpp | |
| parent | faa7d6ba4d73d8e3d89f083deea103afda456a21 (diff) | |
Export language server to wasm. (#5419)
Diffstat (limited to 'source/slang/slang-language-server.cpp')
| -rw-r--r-- | source/slang/slang-language-server.cpp | 422 |
1 files changed, 262 insertions, 160 deletions
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp index 94debde40..80d9c2ef8 100644 --- a/source/slang/slang-language-server.cpp +++ b/source/slang/slang-language-server.cpp @@ -30,6 +30,9 @@ #include "slang-mangle.h" #include "../../tools/platform/performance-counter.h" +#define SLANG_LS_RETURN_ON_SUCCESS(x) { auto _res = (x); if (_res.returnCode == SLANG_OK) return _res; } +#define SLANG_LS_RETURN_ON_FAIL(x) { auto _res = (x); if (SLANG_FAILED(_res.returnCode)) return _res; } + namespace Slang { using namespace LanguageServerProtocol; @@ -42,12 +45,8 @@ ArrayView<const char*> getCommitChars() return makeArrayView(_commitCharsArray, SLANG_COUNT_OF(_commitCharsArray)); } -SlangResult LanguageServer::init(const InitializeParams& args) +SlangResult LanguageServerCore::init(const InitializeParams& args) { - SLANG_RETURN_ON_FAIL(m_connection->initWithStdStreams(JSONRPCConnection::CallStyle::Object)); - - m_typeMap = JSONNativeUtil::getTypeFuncsMap(); - m_workspaceFolders = args.workspaceFolders; m_workspace = new Workspace(); List<URI> rootUris; @@ -59,7 +58,16 @@ SlangResult LanguageServer::init(const InitializeParams& args) return SLANG_OK; } -slang::IGlobalSession* LanguageServer::getOrCreateGlobalSession() +SlangResult LanguageServer::init(const InitializeParams& args) +{ + SLANG_RETURN_ON_FAIL(m_connection->initWithStdStreams(JSONRPCConnection::CallStyle::Object)); + + m_typeMap = JSONNativeUtil::getTypeFuncsMap(); + + return m_core.init(args); +} + +slang::IGlobalSession* LanguageServerCore::getOrCreateGlobalSession() { if (!m_session) { @@ -146,7 +154,7 @@ SlangResult LanguageServer::parseNextMessage() serverInfo.name = "SlangLanguageServer"; serverInfo.version = "1.8"; - if (m_options.isVisualStudio) + if (m_core.m_options.isVisualStudio) { VSInitializeResult vsResult; vsResult.serverInfo = serverInfo; @@ -220,13 +228,18 @@ SlangResult LanguageServer::parseNextMessage() } } -SlangResult LanguageServer::didOpenTextDocument(const DidOpenTextDocumentParams& args) +SlangResult LanguageServerCore::didOpenTextDocument(const DidOpenTextDocumentParams& args) { String canonicalPath = uriToCanonicalPath(args.textDocument.uri); m_workspace->openDoc(canonicalPath, args.textDocument.text); return SLANG_OK; } +SlangResult LanguageServer::didOpenTextDocument(const DidOpenTextDocumentParams& args) +{ + return m_core.didOpenTextDocument(args); +} + static bool isBoolType(Type* t) { auto basicType = as<BasicExpressionType>(t); @@ -515,12 +528,24 @@ HumaneSourceLoc getModuleLoc(SourceManager* manager, ContainerDecl* moduleDecl) SlangResult LanguageServer::hover( const LanguageServerProtocol::HoverParams& args, const JSONValue& responseId) { + auto result = m_core.hover(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<LanguageServerProtocol::Hover> LanguageServerCore::hover( + const LanguageServerProtocol::HoverParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } Index line, col; doc->zeroBasedUTF16LocToOneBasedUTF8Loc(args.position.line, args.position.character, line, col); @@ -531,8 +556,7 @@ SlangResult LanguageServer::hover( Module* parsedModule = version->getOrLoadModule(canonicalPath); if (!parsedModule) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return LanguageServerResult<LanguageServerProtocol::Hover>(); } auto findResult = findASTNodesAt( doc.Ptr(), @@ -544,10 +568,8 @@ SlangResult LanguageServer::hover( col); if (findResult.getCount() == 0 || findResult[0].path.getCount() == 0) { - if (SLANG_SUCCEEDED(tryGetMacroHoverInfo(version, doc, line, col, responseId))) - return SLANG_OK; - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + SLANG_LS_RETURN_ON_SUCCESS(tryGetMacroHoverInfo(version, doc, line, col)); + return std::nullopt; } StringBuilder sb; @@ -836,27 +858,37 @@ SlangResult LanguageServer::hover( } if (sb.getLength() == 0) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } else { hover.contents.kind = "markdown"; hover.contents.value = sb.produceString(); - m_connection->sendResult(&hover, responseId); - return SLANG_OK; + return hover; } } SlangResult LanguageServer::gotoDefinition( const LanguageServerProtocol::DefinitionParams& args, const JSONValue& responseId) { + auto result = m_core.gotoDefinition(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<List<LanguageServerProtocol::Location>> LanguageServerCore::gotoDefinition( + const LanguageServerProtocol::DefinitionParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } Index line, col; doc->zeroBasedUTF16LocToOneBasedUTF8Loc(args.position.line, args.position.character, line, col); @@ -867,8 +899,7 @@ SlangResult LanguageServer::gotoDefinition( Module* parsedModule = version->getOrLoadModule(canonicalPath); if (!parsedModule) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } auto findResult = findASTNodesAt( doc.Ptr(), @@ -880,12 +911,9 @@ SlangResult LanguageServer::gotoDefinition( col); if (findResult.getCount() == 0 || findResult[0].path.getCount() == 0) { - if (SLANG_SUCCEEDED(tryGotoMacroDefinition(version, doc, line, col, responseId))) - return SLANG_OK; - if (SLANG_SUCCEEDED(tryGotoFileInclude(version, doc, line, responseId))) - return SLANG_OK; - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + SLANG_LS_RETURN_ON_SUCCESS(tryGotoMacroDefinition(version, doc, line, col)); + SLANG_LS_RETURN_ON_SUCCESS(tryGotoFileInclude(version, doc, line)); + return std::nullopt; } struct LocationResult { @@ -948,8 +976,7 @@ SlangResult LanguageServer::gotoDefinition( } if (locations.getCount() == 0) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } else { @@ -971,8 +998,7 @@ SlangResult LanguageServer::gotoDefinition( results.add(result); } } - m_connection->sendResult(&results, responseId); - return SLANG_OK; + return results; } } @@ -989,13 +1015,25 @@ template <typename Func> Deferred<Func> makeDeferred(const Func& f) { return Def SlangResult LanguageServer::completion( const LanguageServerProtocol::CompletionParams& args, const JSONValue& responseId) { + auto result = m_core.completion(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + m_connection->sendResult(NullResponse::get(), responseId); + else if (result.result.items.getCount()) + m_connection->sendResult(&result.result.items, responseId); + else + m_connection->sendResult(&result.result.textEditItems, responseId); + return SLANG_OK; +} + +LanguageServerResult<CompletionResult> LanguageServerCore::completion( + const LanguageServerProtocol::CompletionParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } // Don't show completion at case label or after single '>' operator. @@ -1014,8 +1052,7 @@ SlangResult LanguageServer::completion( auto prevCharPos = args.position.character - 2; if (prevCharPos >= 0 && prevCharPos < line.getLength() && line[prevCharPos] != requiredPrevChar) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } } } @@ -1026,8 +1063,7 @@ SlangResult LanguageServer::completion( auto cursorOffset = doc->getOffset(utf8Line, utf8Col); if (cursorOffset == -1 || doc->getText().getLength() == 0) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } // Ajust cursor position to the beginning of the current/last identifier. @@ -1040,8 +1076,7 @@ SlangResult LanguageServer::completion( // Never show suggestions when the user is typing a number. if (cursorOffset + 1 >= 0 && cursorOffset + 1 < doc->getText().getLength() && CharUtil::isDigit(doc->getText()[cursorOffset + 1])) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } // Always create a new workspace version for the completion request since we @@ -1057,7 +1092,6 @@ SlangResult LanguageServer::completion( context.cursorOffset = cursorOffset; context.version = version; context.doc = doc.Ptr(); - context.responseId = responseId; context.canonicalPath = canonicalPath.getUnownedSlice(); context.line = utf8Line; context.col = utf8Col; @@ -1069,22 +1103,15 @@ SlangResult LanguageServer::completion( context.commitCharacterBehavior = CommitCharacterBehavior::Disabled; } - if (SLANG_SUCCEEDED(context.tryCompleteInclude())) - { - return SLANG_OK; - } - if (SLANG_SUCCEEDED(context.tryCompleteImport())) - { - return SLANG_OK; - } + SLANG_LS_RETURN_ON_SUCCESS(context.tryCompleteInclude()); + SLANG_LS_RETURN_ON_SUCCESS(context.tryCompleteImport()); if (args.context.triggerKind == LanguageServerProtocol::kCompletionTriggerKindTriggerCharacter && (args.context.triggerCharacter == "\"" || args.context.triggerCharacter == "/")) { // Trigger characters '"' and '/' are for include only. - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } @@ -1099,49 +1126,48 @@ SlangResult LanguageServer::completion( Module* parsedModule = version->getOrLoadModule(canonicalPath); if (!parsedModule) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } context.parsedModule = parsedModule; - if (SLANG_SUCCEEDED(context.tryCompleteAttributes())) - { - return SLANG_OK; - } + SLANG_LS_RETURN_ON_SUCCESS(context.tryCompleteAttributes()); // Don't generate completion suggestions after typing '['. if (args.context.triggerKind == LanguageServerProtocol::kCompletionTriggerKindTriggerCharacter && args.context.triggerCharacter == "[") { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } - if (SLANG_SUCCEEDED(context.tryCompleteHLSLSemantic())) - { - return SLANG_OK; - } - if (SLANG_SUCCEEDED(context.tryCompleteMemberAndSymbol())) + SLANG_LS_RETURN_ON_SUCCESS(context.tryCompleteHLSLSemantic()); + SLANG_LS_RETURN_ON_SUCCESS(context.tryCompleteMemberAndSymbol()); + return std::nullopt; +} + +SlangResult LanguageServer::completionResolve( + const LanguageServerProtocol::CompletionItem& args, const LanguageServerProtocol::TextEditCompletionItem& editItem, const JSONValue& responseId) +{ + auto result = m_core.completionResolve(args, editItem); + if (SLANG_FAILED(result.returnCode) || result.isNull) { + m_connection->sendResult(NullResponse::get(), responseId); return SLANG_OK; } - m_connection->sendResult(NullResponse::get(), responseId); + m_connection->sendResult(&result.result, responseId); return SLANG_OK; } -SlangResult LanguageServer::completionResolve( - const LanguageServerProtocol::CompletionItem& args, const LanguageServerProtocol::TextEditCompletionItem& editItem, const JSONValue& responseId) +LanguageServerResult<LanguageServerProtocol::CompletionItem> LanguageServerCore::completionResolve( + const LanguageServerProtocol::CompletionItem& args, const LanguageServerProtocol::TextEditCompletionItem& editItem) { if (args.data.getLength() == 0) { if (editItem.textEdit.newText.getLength()) { - m_connection->sendResult(&editItem, responseId); - return SLANG_OK; + return std::nullopt; } - m_connection->sendResult(&args, responseId); - return SLANG_OK; + return args; } LanguageServerProtocol::CompletionItem resolvedItem = args; @@ -1149,8 +1175,7 @@ SlangResult LanguageServer::completionResolve( auto version = m_workspace->getCurrentCompletionVersion(); if (!version || !version->linkage) { - m_connection->sendResult(&resolvedItem, responseId); - return SLANG_OK; + return resolvedItem; } SLANG_AST_BUILDER_RAII(version->linkage->getASTBuilder()); auto& candidateItems = version->linkage->contentAssistInfo.completionSuggestions.candidateItems; @@ -1163,20 +1188,31 @@ SlangResult LanguageServer::completionResolve( resolvedItem.documentation.value = docSB.produceString(); resolvedItem.documentation.kind = "markdown"; } - m_connection->sendResult(&resolvedItem, responseId); - return SLANG_OK; + return resolvedItem; } SlangResult LanguageServer::semanticTokens( const LanguageServerProtocol::SemanticTokensParams& args, const JSONValue& responseId) { + auto result = m_core.semanticTokens(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<LanguageServerProtocol::SemanticTokens> LanguageServerCore::semanticTokens( + const LanguageServerProtocol::SemanticTokensParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } auto version = m_workspace->getCurrentVersion(); @@ -1185,8 +1221,7 @@ SlangResult LanguageServer::semanticTokens( Module* parsedModule = version->getOrLoadModule(canonicalPath); if (!parsedModule) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } auto tokens = getSemanticTokens(version->linkage, parsedModule, canonicalPath.getUnownedSlice(), doc.Ptr()); @@ -1204,11 +1239,10 @@ SlangResult LanguageServer::semanticTokens( SemanticTokens response; response.resultId = ""; response.data = getEncodedTokens(tokens); - m_connection->sendResult(&response, responseId); - return SLANG_OK; + return response; } -String LanguageServer::getExprDeclSignature(Expr* expr, String* outDocumentation, List<Slang::Range<Index>>* outParamRanges) +String LanguageServerCore::getExprDeclSignature(Expr* expr, String* outDocumentation, List<Slang::Range<Index>>* outParamRanges) { if (auto declRefExpr = as<DeclRefExpr>(expr)) { @@ -1285,7 +1319,7 @@ String LanguageServer::getExprDeclSignature(Expr* expr, String* outDocumentation return printer.getString(); } -String LanguageServer::getDeclRefSignature(DeclRef<Decl> declRef, String* outDocumentation, List<Slang::Range<Index>>* outParamRanges) +String LanguageServerCore::getDeclRefSignature(DeclRef<Decl> declRef, String* outDocumentation, List<Slang::Range<Index>>* outParamRanges) { auto version = m_workspace->getCurrentVersion(); SLANG_AST_BUILDER_RAII(version->linkage->getASTBuilder()); @@ -1314,12 +1348,24 @@ String LanguageServer::getDeclRefSignature(DeclRef<Decl> declRef, String* outDoc SlangResult LanguageServer::signatureHelp( const LanguageServerProtocol::SignatureHelpParams& args, const JSONValue& responseId) { + auto result = m_core.signatureHelp(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<LanguageServerProtocol::SignatureHelp> LanguageServerCore::signatureHelp( + const LanguageServerProtocol::SignatureHelpParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } Index line, col; doc->zeroBasedUTF16LocToOneBasedUTF8Loc(args.position.line, args.position.character, line, col); @@ -1330,8 +1376,7 @@ SlangResult LanguageServer::signatureHelp( Module* parsedModule = version->getOrLoadModule(canonicalPath); if (!parsedModule) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } auto findResult = findASTNodesAt( @@ -1345,8 +1390,7 @@ SlangResult LanguageServer::signatureHelp( if (findResult.getCount() == 0) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } AppExprBase* appExpr = nullptr; @@ -1373,14 +1417,12 @@ SlangResult LanguageServer::signatureHelp( } if (!appExpr) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } if (appExpr->argumentDelimeterLocs.getCount() == 0) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } auto funcExpr = appExpr->functionExpr; @@ -1399,8 +1441,7 @@ SlangResult LanguageServer::signatureHelp( } if (!funcExpr) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } SignatureHelp response; @@ -1534,19 +1575,30 @@ SlangResult LanguageServer::signatureHelp( } } - m_connection->sendResult(&response, responseId); - return SLANG_OK; + return response; } SlangResult LanguageServer::documentSymbol( const LanguageServerProtocol::DocumentSymbolParams& args, const JSONValue& responseId) { + auto result = m_core.documentSymbol(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<List<LanguageServerProtocol::DocumentSymbol>> LanguageServerCore::documentSymbol( + const LanguageServerProtocol::DocumentSymbolParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } auto version = m_workspace->getCurrentVersion(); SLANG_AST_BUILDER_RAII(version->linkage->getASTBuilder()); @@ -1554,22 +1606,31 @@ SlangResult LanguageServer::documentSymbol( Module* parsedModule = version->getOrLoadModule(canonicalPath); if (!parsedModule) { + return std::nullopt; + } + List<DocumentSymbol> symbols = getDocumentSymbols(version->linkage, parsedModule, canonicalPath.getUnownedSlice(), doc.Ptr()); + return symbols; +} + +SlangResult LanguageServer::inlayHint(const LanguageServerProtocol::InlayHintParams& args, const JSONValue& responseId) +{ + auto result = m_core.inlayHint(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { m_connection->sendResult(NullResponse::get(), responseId); return SLANG_OK; } - List<DocumentSymbol> symbols = getDocumentSymbols(version->linkage, parsedModule, canonicalPath.getUnownedSlice(), doc.Ptr()); - m_connection->sendResult(&symbols, responseId); + m_connection->sendResult(&result.result, responseId); return SLANG_OK; } -SlangResult LanguageServer::inlayHint(const LanguageServerProtocol::InlayHintParams& args, const JSONValue& responseId) +LanguageServerResult<List<LanguageServerProtocol::InlayHint>> LanguageServerCore::inlayHint(const LanguageServerProtocol::InlayHintParams& args) { String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } auto version = m_workspace->getCurrentVersion(); SLANG_AST_BUILDER_RAII(version->linkage->getASTBuilder()); @@ -1577,8 +1638,7 @@ SlangResult LanguageServer::inlayHint(const LanguageServerProtocol::InlayHintPar Module* parsedModule = version->getOrLoadModule(canonicalPath); if (!parsedModule) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } List<InlayHint> hints = getInlayHints( version->linkage, @@ -1587,8 +1647,7 @@ SlangResult LanguageServer::inlayHint(const LanguageServerProtocol::InlayHintPar doc.Ptr(), args.range, m_inlayHintOptions); - m_connection->sendResult(&hints, responseId); - return SLANG_OK; + return hints; } List<LanguageServerProtocol::TextEdit> translateTextEdits(DocumentVersion* doc, List<Edit>& edits) @@ -1615,12 +1674,24 @@ List<LanguageServerProtocol::TextEdit> translateTextEdits(DocumentVersion* doc, SlangResult LanguageServer::formatting(const LanguageServerProtocol::DocumentFormattingParams& args, const JSONValue& responseId) { + auto result = m_core.formatting(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<List<LanguageServerProtocol::TextEdit>> LanguageServerCore::formatting( + const LanguageServerProtocol::DocumentFormattingParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } if (m_formatOptions.clangFormatLocation.getLength() == 0) m_formatOptions.clangFormatLocation = findClangFormatTool(); @@ -1629,18 +1700,29 @@ SlangResult LanguageServer::formatting(const LanguageServerProtocol::DocumentFor List<TextRange> exclusionRange = extractFormattingExclusionRanges(doc->getText().getUnownedSlice()); auto edits = formatSource(doc->getText().getUnownedSlice(), -1, -1, -1, exclusionRange, options); auto textEdits = translateTextEdits(doc, edits); - m_connection->sendResult(&textEdits, responseId); - return SLANG_OK; + return textEdits; } SlangResult LanguageServer::rangeFormatting(const LanguageServerProtocol::DocumentRangeFormattingParams& args, const JSONValue& responseId) { + auto result = m_core.rangeFormatting(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<List<LanguageServerProtocol::TextEdit>> LanguageServerCore::rangeFormatting( + const LanguageServerProtocol::DocumentRangeFormattingParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } Index endLine, endCol; doc->zeroBasedUTF16LocToOneBasedUTF8Loc(args.range.end.line, args.range.end.character, endLine, endCol); @@ -1653,23 +1735,33 @@ SlangResult LanguageServer::rangeFormatting(const LanguageServerProtocol::Docume List<TextRange> exclusionRange = extractFormattingExclusionRanges(doc->getText().getUnownedSlice()); auto edits = formatSource(doc->getText().getUnownedSlice(), args.range.start.line, args.range.end.line, endOffset, exclusionRange, options); auto textEdits = translateTextEdits(doc, edits); - m_connection->sendResult(&textEdits, responseId); - return SLANG_OK; + return textEdits; } SlangResult LanguageServer::onTypeFormatting(const LanguageServerProtocol::DocumentOnTypeFormattingParams& args, const JSONValue& responseId) { + auto result = m_core.onTypeFormatting(args); + if (SLANG_FAILED(result.returnCode) || result.isNull) + { + m_connection->sendResult(NullResponse::get(), responseId); + return SLANG_OK; + } + m_connection->sendResult(&result.result, responseId); + return SLANG_OK; +} + +LanguageServerResult<List<LanguageServerProtocol::TextEdit>> LanguageServerCore::onTypeFormatting( + const LanguageServerProtocol::DocumentOnTypeFormattingParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); RefPtr<DocumentVersion> doc; if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc)) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } if (args.ch == ":" && !doc->getLine((Int)args.position.line + 1).trim().startsWith("case ")) { - m_connection->sendResult(NullResponse::get(), responseId); - return SLANG_OK; + return std::nullopt; } if (m_formatOptions.clangFormatLocation.getLength() == 0) m_formatOptions.clangFormatLocation = findClangFormatTool(); @@ -1682,20 +1774,18 @@ SlangResult LanguageServer::onTypeFormatting(const LanguageServerProtocol::Docum List<TextRange> exclusionRange = extractFormattingExclusionRanges(doc->getText().getUnownedSlice()); auto edits = formatSource(doc->getText().getUnownedSlice(), args.position.line, args.position.line, cursorOffset, exclusionRange, options); auto textEdits = translateTextEdits(doc, edits); - m_connection->sendResult(&textEdits, responseId); - return SLANG_OK; + return textEdits; } void LanguageServer::publishDiagnostics() { - if (std::chrono::system_clock::now() - m_lastDiagnosticUpdateTime < std::chrono::milliseconds(1000)) { return; } m_lastDiagnosticUpdateTime = std::chrono::system_clock::now(); - auto version = m_workspace->getCurrentVersion(); + auto version = m_core.m_workspace->getCurrentVersion(); SLANG_AST_BUILDER_RAII(version->linkage->getASTBuilder()); // Send updates to clear diagnostics for files that no longer have any messages. @@ -1747,7 +1837,7 @@ void LanguageServer::updatePredefinedMacros(const JSONValue& macros) List<String> predefinedMacros; if (SLANG_SUCCEEDED(converter.convert(macros, &predefinedMacros))) { - if (m_workspace->updatePredefinedMacros(predefinedMacros)) + if (m_core.m_workspace->updatePredefinedMacros(predefinedMacros)) { sendRefreshRequests(m_connection); } @@ -1764,7 +1854,7 @@ void LanguageServer::updateSearchPaths(const JSONValue& value) List<String> searchPaths; if (SLANG_SUCCEEDED(converter.convert(value, &searchPaths))) { - if (m_workspace->updateSearchPaths(searchPaths)) + if (m_core.m_workspace->updateSearchPaths(searchPaths)) { sendRefreshRequests(m_connection); } @@ -1781,7 +1871,7 @@ void LanguageServer::updateSearchInWorkspace(const JSONValue& value) bool searchPaths; if (SLANG_SUCCEEDED(converter.convert(value, &searchPaths))) { - if (m_workspace->updateSearchInWorkspace(searchPaths)) + if (m_core.m_workspace->updateSearchInWorkspace(searchPaths)) { sendRefreshRequests(m_connection); } @@ -1800,15 +1890,15 @@ void LanguageServer::updateCommitCharacters(const JSONValue& jsonValue) { if (value == "on") { - m_commitCharacterBehavior = CommitCharacterBehavior::All; + m_core.m_commitCharacterBehavior = CommitCharacterBehavior::All; } else if (value == "off") { - m_commitCharacterBehavior = CommitCharacterBehavior::Disabled; + m_core.m_commitCharacterBehavior = CommitCharacterBehavior::Disabled; } else { - m_commitCharacterBehavior = CommitCharacterBehavior::MembersOnly; + m_core.m_commitCharacterBehavior = CommitCharacterBehavior::MembersOnly; } } } @@ -1819,17 +1909,17 @@ void LanguageServer::updateFormattingOptions(const JSONValue& clangFormatLoc, co auto container = m_connection->getContainer(); JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink()); if (clangFormatLoc.isValid()) - converter.convert(clangFormatLoc, &m_formatOptions.clangFormatLocation); + converter.convert(clangFormatLoc, &m_core.m_formatOptions.clangFormatLocation); if (clangFormatStyle.isValid()) - converter.convert(clangFormatStyle, &m_formatOptions.style); + converter.convert(clangFormatStyle, &m_core.m_formatOptions.style); if (clangFormatFallbackStyle.isValid()) - converter.convert(clangFormatFallbackStyle, &m_formatOptions.fallbackStyle); + converter.convert(clangFormatFallbackStyle, &m_core.m_formatOptions.fallbackStyle); if (allowLineBreakOnType.isValid()) - converter.convert(allowLineBreakOnType, &m_formatOptions.allowLineBreakInOnTypeFormatting); + converter.convert(allowLineBreakOnType, &m_core.m_formatOptions.allowLineBreakInOnTypeFormatting); if (allowLineBreakInRange.isValid()) - converter.convert(allowLineBreakInRange, &m_formatOptions.allowLineBreakInRangeFormatting); - if (m_formatOptions.style.getLength() == 0) - m_formatOptions.style = Slang::FormatOptions().style; + converter.convert(allowLineBreakInRange, &m_core.m_formatOptions.allowLineBreakInRangeFormatting); + if (m_core.m_formatOptions.style.getLength() == 0) + m_core.m_formatOptions.style = Slang::FormatOptions().style; } void LanguageServer::updateInlayHintOptions(const JSONValue& deducedTypes, const JSONValue& parameterNames) @@ -1840,13 +1930,13 @@ void LanguageServer::updateInlayHintOptions(const JSONValue& deducedTypes, const bool showParameterNames = false; converter.convert(deducedTypes, &showDeducedType); converter.convert(parameterNames, &showParameterNames); - if (showDeducedType != m_inlayHintOptions.showDeducedType || showParameterNames != m_inlayHintOptions.showParameterNames) + if (showDeducedType != m_core.m_inlayHintOptions.showDeducedType || showParameterNames != m_core.m_inlayHintOptions.showParameterNames) { m_connection->sendCall( UnownedStringSlice("workspace/inlayHint/refresh"), JSONValue::makeInt(0)); } - m_inlayHintOptions.showDeducedType = showDeducedType; - m_inlayHintOptions.showParameterNames = showParameterNames; + m_core.m_inlayHintOptions.showDeducedType = showDeducedType; + m_core.m_inlayHintOptions.showParameterNames = showParameterNames; } void LanguageServer::updateTraceOptions(const JSONValue& value) @@ -1921,7 +2011,7 @@ void LanguageServer::logMessage(int type, String message) m_connection->sendCall(LanguageServerProtocol::LogMessageParams::methodName, &args); } -FormatOptions LanguageServer::getFormatOptions(Workspace* workspace, FormatOptions inOptions) +FormatOptions LanguageServerCore::getFormatOptions(Workspace* workspace, FormatOptions inOptions) { FormatOptions result = inOptions; if (workspace->rootDirectories.getCount()) @@ -1934,8 +2024,8 @@ FormatOptions LanguageServer::getFormatOptions(Workspace* workspace, FormatOptio return result; } -SlangResult LanguageServer::tryGetMacroHoverInfo( - WorkspaceVersion* version, DocumentVersion* doc, Index line, Index col, JSONValue responseId) +LanguageServerResult<LanguageServerProtocol::Hover> LanguageServerCore::tryGetMacroHoverInfo( + WorkspaceVersion* version, DocumentVersion* doc, Index line, Index col) { Index startOffset = 0; auto identifier = doc->peekIdentifier(line, col, startOffset); @@ -1981,12 +2071,11 @@ SlangResult LanguageServer::tryGetMacroHoverInfo( appendDefinitionLocation(sb, m_workspace, humaneLoc); hover.contents.kind = "markdown"; hover.contents.value = sb.produceString(); - m_connection->sendResult(&hover, responseId); - return SLANG_OK; + return hover; } -SlangResult LanguageServer::tryGotoMacroDefinition( - WorkspaceVersion* version, DocumentVersion* doc, Index line, Index col, JSONValue responseId) +LanguageServerResult<List<Location>> LanguageServerCore::tryGotoMacroDefinition( + WorkspaceVersion* version, DocumentVersion* doc, Index line, Index col) { Index startOffset = 0; auto identifier = doc->peekIdentifier(line, col, startOffset); @@ -1997,7 +2086,9 @@ SlangResult LanguageServer::tryGotoMacroDefinition( return SLANG_FAIL; auto humaneLoc = version->linkage->getSourceManager()->getHumaneLoc(def->loc, SourceLocType::Actual); - LanguageServerProtocol::Location result; + List<LanguageServerProtocol::Location> results; + results.setCount(1); + auto& result = results[0]; result.uri = URI::fromLocalFilePath(humaneLoc.pathInfo.foundPath.getUnownedSlice()).uri; Index outLine, outCol; doc->oneBasedUTF8LocToZeroBasedUTF16Loc(humaneLoc.line, humaneLoc.column, outLine, outCol); @@ -2005,12 +2096,11 @@ SlangResult LanguageServer::tryGotoMacroDefinition( result.range.start.character = (int)outCol; result.range.end.line = (int)outLine; result.range.end.character = (int)(outCol + identifier.getLength()); - m_connection->sendResult(&result, responseId); - return SLANG_OK; + return results; } -SlangResult LanguageServer::tryGotoFileInclude( - WorkspaceVersion* version, DocumentVersion* doc, Index line, JSONValue responseId) +LanguageServerResult<List<Location>> LanguageServerCore::tryGotoFileInclude( + WorkspaceVersion* version, DocumentVersion* doc, Index line) { auto lineContent = doc->getLine(line).trim(); if (!lineContent.startsWith("#") || lineContent.indexOf(UnownedStringSlice("include")) == -1) @@ -2021,14 +2111,15 @@ SlangResult LanguageServer::tryGotoFileInclude( version->linkage->getSourceManager()->getHumaneLoc(include.loc, SourceLocType::Actual); if (includeLoc.line == line && includeLoc.pathInfo.foundPath == doc->getPath()) { - LanguageServerProtocol::Location result; + List<LanguageServerProtocol::Location> results; + results.setCount(1); + auto& result = results[0]; result.uri = URI::fromLocalFilePath(include.path.getUnownedSlice()).uri; result.range.start.line = 0; result.range.start.character = 0; result.range.end.line = 0; result.range.end.character = 0; - m_connection->sendResult(&result, responseId); - return SLANG_OK; + return results; } } return SLANG_FAIL; @@ -2267,17 +2358,28 @@ void LanguageServer::processCommands() SlangResult LanguageServer::didCloseTextDocument(const DidCloseTextDocumentParams& args) { + resetDiagnosticUpdateTime(); + return m_core.didCloseTextDocument(args); +} + +SlangResult LanguageServerCore::didCloseTextDocument(const DidCloseTextDocumentParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); m_workspace->closeDoc(canonicalPath); - resetDiagnosticUpdateTime(); return SLANG_OK; } + SlangResult LanguageServer::didChangeTextDocument(const DidChangeTextDocumentParams& args) { + resetDiagnosticUpdateTime(); + return m_core.didChangeTextDocument(args); +} + +SlangResult LanguageServerCore::didChangeTextDocument(const DidChangeTextDocumentParams& args) +{ String canonicalPath = uriToCanonicalPath(args.textDocument.uri); for (auto change : args.contentChanges) m_workspace->changeDoc(canonicalPath, change.range, change.text); - resetDiagnosticUpdateTime(); return SLANG_OK; } @@ -2297,7 +2399,7 @@ SlangResult LanguageServer::didChangeConfiguration( void LanguageServer::update() { - if (!m_workspace) + if (!m_core.m_workspace) return; publishDiagnostics(); } |
