Open credmp opened 1 year ago
First of all: yes! Thanks for putting time in this. If you need help with the repl extensions we made and the ideservices, just shout out.
Will look into this current issue tomorrow.
By the way does the emacs LSP client support Semantic highlighting? Because we depend on that to mimick highlighters based on Rascal generated parsers.
The client supports the semantic highlighting indeed. Relevant changelog: https://emacs-lsp.github.io/lsp-mode/blog/2020/7.0-release/#semantic-highlights
When I enable semantic-highlighting the following are the client capabilities:
ClientCapabilities [
workspace = WorkspaceClientCapabilities [
applyEdit = true
workspaceEdit = WorkspaceEditCapabilities [
documentChanges = true
resourceOperations = ArrayList (
"create",
"rename",
"delete"
)
failureHandling = null
normalizesLineEndings = null
changeAnnotationSupport = null
]
didChangeConfiguration = null
didChangeWatchedFiles = DidChangeWatchedFilesCapabilities [
relativePatternSupport = null
dynamicRegistration = true
]
symbol = SymbolCapabilities [
symbolKind = SymbolKindCapabilities [
valueSet = ArrayList (
File,
Module,
Namespace,
Package,
Class,
Method,
Property,
Field,
Constructor,
Enum,
Interface,
Function,
Variable,
Constant,
String,
Number,
Boolean,
Array,
Object,
Key,
Null,
EnumMember,
Struct,
Event,
Operator,
TypeParameter
)
]
tagSupport = null
resolveSupport = null
dynamicRegistration = null
]
executeCommand = ExecuteCommandCapabilities [
dynamicRegistration = false
]
workspaceFolders = true
configuration = true
semanticTokens = SemanticTokensWorkspaceCapabilities [
refreshSupport = false
]
codeLens = CodeLensWorkspaceCapabilities [
refreshSupport = true
]
fileOperations = FileOperationsWorkspaceCapabilities [
didCreate = false
willCreate = false
didRename = true
willRename = true
didDelete = false
willDelete = false
dynamicRegistration = null
]
inlayHint = null
inlineValue = null
diagnostics = null
]
textDocument = TextDocumentClientCapabilities [
synchronization = SynchronizationCapabilities [
willSave = true
willSaveWaitUntil = true
didSave = true
dynamicRegistration = null
]
completion = CompletionCapabilities [
completionItem = CompletionItemCapabilities [
snippetSupport = true
commitCharactersSupport = null
documentationFormat = ArrayList (
"markdown",
"plaintext"
)
deprecatedSupport = true
preselectSupport = null
tagSupport = null
insertReplaceSupport = true
resolveSupport = CompletionItemResolveSupportCapabilities [
properties = ArrayList (
"documentation",
"detail",
"additionalTextEdits",
"command"
)
]
insertTextModeSupport = CompletionItemInsertTextModeSupportCapabilities [
valueSet = ArrayList (
AsIs,
AdjustIndentation
)
]
labelDetailsSupport = null
]
completionItemKind = null
contextSupport = true
insertTextMode = null
completionList = null
dynamicRegistration = true
]
hover = HoverCapabilities [
contentFormat = ArrayList (
"markdown",
"plaintext"
)
dynamicRegistration = true
]
signatureHelp = SignatureHelpCapabilities [
signatureInformation = SignatureInformationCapabilities [
documentationFormat = null
parameterInformation = ParameterInformationCapabilities [
labelOffsetSupport = true
]
activeParameterSupport = null
]
contextSupport = null
dynamicRegistration = true
]
references = null
documentHighlight = null
documentSymbol = DocumentSymbolCapabilities [
symbolKind = SymbolKindCapabilities [
valueSet = ArrayList (
File,
Module,
Namespace,
Package,
Class,
Method,
Property,
Field,
Constructor,
Enum,
Interface,
Function,
Variable,
Constant,
String,
Number,
Boolean,
Array,
Object,
Key,
Null,
EnumMember,
Struct,
Event,
Operator,
TypeParameter
)
]
hierarchicalDocumentSymbolSupport = true
tagSupport = null
labelSupport = null
dynamicRegistration = null
]
formatting = FormattingCapabilities [
dynamicRegistration = true
]
rangeFormatting = RangeFormattingCapabilities [
dynamicRegistration = true
]
onTypeFormatting = OnTypeFormattingCapabilities [
dynamicRegistration = true
]
declaration = DeclarationCapabilities [
linkSupport = true
dynamicRegistration = true
]
definition = DefinitionCapabilities [
linkSupport = true
dynamicRegistration = true
]
typeDefinition = TypeDefinitionCapabilities [
linkSupport = true
dynamicRegistration = true
]
implementation = ImplementationCapabilities [
linkSupport = true
dynamicRegistration = true
]
codeAction = CodeActionCapabilities [
codeActionLiteralSupport = CodeActionLiteralSupportCapabilities [
codeActionKind = CodeActionKindCapabilities [
valueSet = ArrayList (
"",
"quickfix",
"refactor",
"refactor.extract",
"refactor.inline",
"refactor.rewrite",
"source",
"source.organizeImports"
)
]
]
isPreferredSupport = true
disabledSupport = null
dataSupport = true
resolveSupport = CodeActionResolveSupportCapabilities [
properties = ArrayList (
"edit",
"command"
)
]
honorsChangeAnnotations = null
dynamicRegistration = true
]
codeLens = null
documentLink = DocumentLinkCapabilities [
tooltipSupport = true
dynamicRegistration = true
]
colorProvider = null
rename = RenameCapabilities [
prepareSupport = true
prepareSupportDefaultBehavior = null
honorsChangeAnnotations = null
dynamicRegistration = true
]
publishDiagnostics = PublishDiagnosticsCapabilities [
relatedInformation = true
tagSupport = Either [
left = null
right = DiagnosticsTagSupport [
valueSet = ArrayList (
Unnecessary,
Deprecated
)
]
]
versionSupport = true
codeDescriptionSupport = null
dataSupport = null
]
foldingRange = null
typeHierarchy = TypeHierarchyCapabilities [
dynamicRegistration = true
]
callHierarchy = CallHierarchyCapabilities [
dynamicRegistration = false
]
selectionRange = SelectionRangeCapabilities [
dynamicRegistration = true
]
semanticTokens = SemanticTokensCapabilities [
requests = SemanticTokensClientCapabilitiesRequests [
range = Either [
left = true
right = null
]
full = Either [
left = true
right = null
]
]
tokenTypes = ArrayList (
"comment",
"keyword",
"string",
"number",
"regexp",
"operator",
"namespace",
"type",
"struct",
"class",
"interface",
"enum",
"typeParameter",
"function",
"method",
"member",
"property",
"event",
"macro",
"variable",
"parameter",
"label",
"enumConstant",
"enumMember",
"dependent",
"concept"
)
tokenModifiers = ArrayList (
"declaration",
"definition",
"implementation",
"readonly",
"static",
"deprecated",
"abstract",
"async",
"modification",
"documentation",
"defaultLibrary"
)
formats = ArrayList (
"relative"
)
overlappingTokenSupport = null
multilineTokenSupport = null
serverCancelSupport = null
augmentsSyntaxTokens = null
dynamicRegistration = true
]
moniker = null
linkedEditingRange = LinkedEditingRangeCapabilities [
dynamicRegistration = true
]
inlayHint = null
inlineValue = null
diagnostic = null
]
notebookDocument = null
window = WindowClientCapabilities [
workDoneProgress = true
showMessage = null
showDocument = ShowDocumentCapabilities [
support = true
]
]
general = null
experimental = null
]
Ok. We didn't implement the completion capability yet. It works in the terminal in Rascal because that is implemented independently of the IDE. The completion support in the VScode editor is a language agnostic default feature of VScode.
Ah, I did a quick search of the code for the word 'completion' so I made the assumption that it was working. So for now it is just the semantic highlighting and then the IDEServices/REPL. Those are things I need to figure out how to do still, but then I suggest we close this issue and revisit the functionality when it is implemented in the LS. Agreed?
Let's turn this into a feature request. We can leave it open until we get to it. Of course we'll do it for rascal and DSLs in Rascal at once.
Alright, that is beautiful! I will finish up the Emacs integration (making a new major mode with LSP) and then will look at the integrations of the repl.
This sounds like a nice project.
If you want to know which capabilities the rascal-lsp supports, take a look here:
Note, we also extend the LSP protocol a bit, see:
supplyIDEServicesConfiguration
)Have fun!
Let's turn this into a feature request. We can leave it open until we get to it. Of course we'll do it for rascal and DSLs in Rascal at once.
For rascal we already have an issue tracking this: https://github.com/usethesource/rascal-language-servers/issues/12
For parametric the story is even stranger. Our LanguageService
adt contains an entry for the completer: https://github.com/usethesource/rascal-language-servers/blob/13e9185f01e15bf812b027403dec0655f06c2d07/rascal-lsp/src/main/rascal/util/LanguageServer.rsc#L68
But we ignore that in the implementation. So that's not good. (I've made an issue tracking it #213, as I think both cases are quite different in their implementation and trade-offs.)
Thanks @DavyLandman! I will post back with my progress on the mode for Emacs. Being able to properly edit Rascal and have proper highlighting is already a very nice thing. I believe the integration in emacs itself for the repl (send to repl / click on urls) should be interesting. In the Clojure world there is a similar effort with nrepl, perhaps it is possible to leverage that functionality.
@credmp technically starting up a rascal terminal is pretty easy; it's a jvm system call and you have to pass in the right ports such that the terminal can connect with the LSP server. After that all the IDE integrations run via the existing LSP connection. For example (and this one is rather complex to show all the facets involved):
There are also simpler messages outside of the standard protocol that are handled by the client, such as registering new URI schemes. The extended JSON-RPC messages and notifications labels are alll prefixed with "rascal/".
Describe the bug
I have been working on integrating rascal support into Emacs. I use emacs-lsp for this task, as it is the defacto implementation of an LSP client for Emacs.
The client sends an initialization request and the server responds with the provided capabilities. From my research into the project one of the capabilities should be completion. When answering the client, the server does not indicate the support for completion.
To Reproduce
Client initialize:
The server response:
Relevant (doom) emacs configuration:
Expected behavior
The server should indicate support for completion.