Support for clojure via clojure-lsp

This commit is contained in:
Miguel de Benito Delgado
2025-06-28 08:31:52 +00:00
parent c7ac81b895
commit 211b72042c
4 changed files with 31 additions and 227 deletions
+4
View File
@@ -197,6 +197,10 @@ class LanguageServer:
from multilspy.language_servers.intelephense.intelephense import Intelephense
return Intelephense(config, logger, repository_root_path)
elif config.code_language == Language.CLOJURE:
from multilspy.language_servers.clojure_lsp.clojure_lsp import ClojureLSP
return ClojureLSP(config, logger, repository_root_path)
else:
logger.log(f"Language {config.code_language} is not supported", logging.ERROR)
raise MultilspyException(f"Language {config.code_language} is not supported")
@@ -1,5 +1,5 @@
"""
Provides Rust specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Rust.
Provides Clojure specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Clojure.
"""
import asyncio
@@ -11,8 +11,6 @@ import pathlib
from contextlib import asynccontextmanager
from typing import AsyncIterator
from overrides import override
from multilspy.multilspy_logger import MultilspyLogger
from multilspy.language_server import LanguageServer
from multilspy.lsp_protocol_handler.server import ProcessLaunchInfo
@@ -40,11 +38,10 @@ class ClojureLSP(LanguageServer):
"clojure",
)
self.server_ready = asyncio.Event()
self.initialize_searcher_command_available = asyncio.Event()
self.resolve_main_method_available = asyncio.Event()
self.service_ready_event = asyncio.Event()
@override
def is_ignored_dirname(self, dirname: str) -> bool:
return super().is_ignored_dirname(dirname) or dirname in ["target"]
def setup_runtime_dependencies(self, logger: MultilspyLogger, config: MultilspyConfig) -> str:
"""
Setup runtime dependencies for clojure-lsp.
@@ -162,16 +159,15 @@ class ClojureLSP(LanguageServer):
init_response = await self.server.send.initialize(initialize_params)
assert init_response["capabilities"]["textDocumentSync"]["change"] == 2
assert "completionProvider" in init_response["capabilities"]
assert init_response["capabilities"]["completionProvider"] == {
"resolveProvider": True,
"triggerCharacters": [":", ".", "'", "("],
"completionItem": {"labelDetailsSupport": True},
}
# Clojure-lsp completion provider capabilities are more flexible than other servers
completion_provider = init_response["capabilities"]["completionProvider"]
assert completion_provider["resolveProvider"] == True
assert "triggerCharacters" in completion_provider
self.server.notify.initialized({})
# after initialize, Clojure-lsp is ready to serve
self.server_ready.set()
self.completions_available.set()
await self.server_ready.wait()
yield self
await self.server.shutdown()
@@ -1,30 +1,19 @@
{
"_description": "Parameters sent by multilspy to initialize clojure-lsp (LSP v3.17)",
"processId": "os.getpid()",
"processId": null,
"clientInfo": {
"name": "multilspy",
"version": "0.1.0"
},
"locale": "en",
"rootPath": "$rootPath",
"rootUri": "$rootUri",
"rootPath": "$rootPath",
"capabilities": {
"workspace": {
"applyEdit": true,
"workspaceEdit": {
"documentChanges": true,
"resourceOperations": [
"create",
"rename",
"delete"
]
},
"configuration": true,
"didChangeWatchedFiles": {
"dynamicRegistration": true
"documentChanges": true
},
"symbol": {
"dynamicRegistration": true,
"symbolKind": {
"valueSet": [
1,
@@ -56,23 +45,12 @@
]
}
},
"executeCommand": {
"dynamicRegistration": true
},
"workspaceFolders": true,
"semanticTokens": {
"refreshSupport": true
},
"codeLens": {
"refreshSupport": true
},
"fileOperations": {
"dynamicRegistration": true,
"didRename": true,
"willRename": true
}
"workspaceFolders": true
},
"textDocument": {
"synchronization": {
"didSave": true
},
"publishDiagnostics": {
"relatedInformation": true,
"tagSupport": {
@@ -80,107 +58,29 @@
1,
2
]
},
"codeDescriptionSupport": true,
"dataSupport": true
}
},
"synchronization": {
"dynamicRegistration": true,
"didSave": true
"definition": {
"linkSupport": true
},
"references": {},
"completion": {
"dynamicRegistration": true,
"contextSupport": true,
"completionItem": {
"snippetSupport": true,
"documentationFormat": [
"markdown",
"plaintext"
],
"deprecatedSupport": true,
"preselectSupport": true,
"tagSupport": {
"valueSet": [
1
]
},
"insertReplaceSupport": true,
"resolveSupport": {
"properties": [
"documentation",
"detail",
"additionalTextEdits"
]
}
},
"completionItemKind": {
"valueSet": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25
]
}
},
"hover": {
"dynamicRegistration": true,
"contentFormat": [
"markdown",
"plaintext"
]
},
"signatureHelp": {
"dynamicRegistration": true,
"signatureInformation": {
"documentationFormat": [
"markdown",
"plaintext"
],
"parameterInformation": {
"labelOffsetSupport": true
}
}
},
"declaration": {
"dynamicRegistration": true,
"linkSupport": true
},
"definition": {
"dynamicRegistration": true,
"linkSupport": true
},
"implementation": {
"dynamicRegistration": true,
"linkSupport": true
},
"references": {
"dynamicRegistration": true
},
"documentHighlight": {
"dynamicRegistration": true
},
"documentSymbol": {
"dynamicRegistration": true,
"hierarchicalDocumentSymbolSupport": true,
"symbolKind": {
"valueSet": [
1,
@@ -210,98 +110,6 @@
25,
26
]
},
"hierarchicalDocumentSymbolSupport": true
},
"codeAction": {
"dynamicRegistration": true,
"isPreferredSupport": true,
"resolveSupport": {
"properties": [
"edit"
]
},
"codeActionLiteralSupport": {
"codeActionKind": {
"valueSet": [
"",
"quickfix",
"refactor",
"refactor.extract",
"refactor.inline",
"refactor.rewrite",
"source",
"source.organizeImports"
]
}
}
},
"codeLens": {
"dynamicRegistration": true
},
"formatting": {
"dynamicRegistration": true
},
"rangeFormatting": {
"dynamicRegistration": true
},
"rename": {
"dynamicRegistration": true,
"prepareSupport": true
},
"foldingRange": {
"dynamicRegistration": true,
"lineFoldingOnly": true
},
"selectionRange": {
"dynamicRegistration": true
},
"semanticTokens": {
"dynamicRegistration": true,
"tokenTypes": [
"namespace",
"class",
"function",
"method",
"variable",
"keyword",
"string",
"comment",
"number",
"regexp",
"operator",
"macro"
],
"tokenModifiers": [
"declaration",
"definition",
"readonly",
"static",
"deprecated",
"documentation"
],
"formats": [
"relative"
],
"requests": {
"range": true,
"full": {
"delta": false
}
}
},
"linkedEditingRange": {
"dynamicRegistration": true
},
"callHierarchy": {
"dynamicRegistration": true
}
},
"window": {
"workDoneProgress": true,
"showMessage": {
"messageActionItem": {
"additionalPropertiesSupport": true
}
}
},
@@ -309,20 +117,13 @@
"positionEncodings": [
"utf-16"
]
},
"experimental": {
"testTree": true,
"projectTree": true
}
},
"initializationOptions": {
"dependency-scheme": "jar",
"document-formatting?": true,
"document-range-formatting?": true,
"text-document-sync-kind": "incremental",
"semantic-tokens?": true
"text-document-sync-kind": "incremental"
},
"trace": "verbose",
"trace": "off",
"workspaceFolders": [
{
"uri": "$uri",
+3
View File
@@ -38,6 +38,7 @@ class Language(str, Enum):
DART = "dart"
CPP = "cpp"
PHP = "php"
CLOJURE = "clojure"
def __str__(self) -> str:
return self.value
@@ -68,6 +69,8 @@ class Language(str, Enum):
return FilenameMatcher("*.dart")
case self.PHP:
return FilenameMatcher("*.php")
case self.CLOJURE:
return FilenameMatcher("*.clj", "*.cljs", "*.cljc", "*.edn")
case _:
raise ValueError(f"Unhandled language: {self}")