It would be very handy if parts of the specification could be read by machines.
This would help developing SDKs for typed languages a lot, as many types can be auto generated.
Besides, there are some inconsistencies in non-normative parts of the specification that could be easily fixed (e.g. interfaces vs exported interfaces, params vs param).
Something like this would be awesome in addition to the existing specification:
(comments removed to keep it short)
interface RequestMessage<TMethod extends string, TParams> {
id: number | string;
method: TMethod;
params: TParams
}
interface ResponseMessage<TResult, TError> {
id: number | string;
result?: TResult;
error?: ResponseError<TError>;
}
interface Request<TRequest, TResponse> {}
interface Notification<TRequest> {}
// ...
type InitializeRequest = Request<
RequestMessage<"initialize", InitializeParams>,
ResponseMessage<InitializeResult, InitializeError>
>;
type ShutdownRequest = Request<
RequestMessage<"shutdown", undefined>,
ResponseMessage<undefined, undefined>
>;
type ShowMessageNotification = Notification<
RequestMessage<"window/showMessage", ShowMessageParams>
>;
What do you think? I can offer to add these additional typescript definitions for all of the about 30 notifications / requests.
The link mentioned in the first comment in #25 is not valid anymore and #40 only covers the types, not the actual protocol (methods, request/notification, expected response types and so on).
I basically was looking for protocol.ts.
Agree with @gorkem that a machine readable specification should be in JSON Schema since this is more universal. There are quite some tools out there to generate interface files from JSON for different languages.
JSON schema would be awesome, and also allow to be more specific than TS interfaces. For example, you can apply RegExp constraints to strings.
An editor will need to have fast response times from a server to be interactive.
It looks to me that a text based protocol will hurt this interactivity. It is well known that text processing is much slower than well structured binary data.
So, why not use protocol buffers:
https://github.com/google/upb
With upb the backend can be chosen:
The protocol is defined with an schema and is fully machine-readable.
@vicencb the protocol buffer is about the transport. Since the message header allows to specify a content type we can send binary data if this is necessary due to performance.
This issue is about having the specification in a machine readable from.
Not sure if you want to collect examples of what's difficult to parse here in this issue, but I just came across another one and thought it worth noting.. The response to textDocument/prepareRename is documented as Range \| { range: Range, placeholder: string } \| null.
However this text only appears in the results: note against the request, there's no typescript codeblock with the definition. This means if you want to codegen a class for the range+placeholder, you need to regex it out, but the same line contains a bunch of english:
- result:
Range\|{ range: Range, placeholder: string }\|nulldescribing the range of the string to rename and optionally a placeholder text of the string content to be renamed. Ifnullis returned then it is deemed that a 'textDocument/rename' request is not valid at the given position.
I really want to avoid too many special cases to make it easier to keep my classes up-to-date, but now I have a regex like \* result:[^\.]*({.*}) to try and extract this reliably. The rest of the spec outgrew my regexes (they got really complicated) and I ended up writing a small TypeScript parser in order to extract everything from here). I don't know how the other servers are doing it, but it feels like a bit of a burden :-(
Another inconsistency found while parsing:
Some notifications list their params as params: void and others use params: none. As far as I can tell, these mean the same, which is the params field can be omitted.
@DanTup when I started to convert this to JSON schema I used a TS compiler to parse the TS file from https://github.com/Microsoft/vscode-languageserver-node/blob/dbaeumer/464/protocol/src/protocol.ts#L1 which should give the best result.
@dbaeumer Thanks! That might've been a better thing to parse when I started, though I now have a fairly-complete parser for the spec and it's probably not worth changing. I was just noting inconsistencies I noticed in the hope the official spec might become friendlier for parsing.
Out of interest, you say started to convert to JSON schema - is that still in progress? Will it become an official schema? I don't want to mess with the parser too much now it (mostly) works, but switching from a TS-parser-written-in-Dart to something structured would definitely be nice.
@DanTup it is on hold right now due to other priorities. As always community help is appreciated here.
Just another vote for JSON-Schema or some sort of protocol.json as core first-class part of the LSP project's spec efforts. I had previously for example utilized https://github.com/Microsoft/vscode-debugadapter-node/blob/master/debugProtocol.json to generate code scaffolds with great success, and was "almost sure something like LSP must have something equivalent --- by now" until just minutes ago. Looks like not-yet.. but should substantially ease the burden on contributors to the ecosystem (client and server implementations written in countless languages) especially when it comes to them keeping up with new versions (swiftly or at-all), supporting multiple versions, remaining motivated to not abandon their client or server implementation, or if that happens easier and swifter springing up of alternative implementations etc.
Alternatively the question could be whether the TypeScript project offers-and-supports (or whether it should) some sort of baseline / stable / maintained .d.ts-to-JSON converter that keeps up with TS' own movements. Then anyone could use that for both LSP protocols and whatever else floats around in .d.ts land.
I agree with this and when I last looked into this I was experimenting with converting the d.ts to JSON schema automatically. This would be a great opportunity for the community :-)
Out of curiosity: Are there any good tools available for this task? Have you encountered any pitfalls with the automatic conversion so far?
A little bit off-topic: For the other way around I like using json-schema-to-typescript.
Alternatively the question could be whether the TypeScript project offers-and-supports (or whether it should) some sort of baseline / stable / maintained .d.ts-to-JSON converter that keeps up with TS' own movements. Then anyone could use that for both LSP protocols and whatever else floats around in .d.ts land.
I've used https://github.com/YousefED/typescript-json-schema with great success for this. We could use that to generate the initial schema, manually optimize it, commit it and then delete the original TypeScript and start generating it from the JSON schema with https://github.com/bcherny/json-schema-to-typescript.
I've some success to report with:
ts-json-schema-generatorHere's the whole gist (or binder, if you're into that sort of thing), and the schema as JSON (or YAML).
It hasn't been exhaustively tested, but _by inspection_ appears to be fairly thorough. I'd love to see something like this made more official, but will probably keep tinkering with it.
:clap: Thanks to @domoritz, for helping me get voids added to ts-json-schema-generator!
Would love to see JSON schema be the first-class spec as it is with DAP. The fact that the TS and JSON data types don't align perfectly came up in https://github.com/microsoft/language-server-protocol/pull/833#discussion_r335145613.
Sounds good! Given there is some precedent with DAP, is the schema...
As a downstream consumer of the spec, all of these properties would be desirable.
A canonical representation in YAML, TOML, or some other JSON-data-model-but-not-braces-and-escaped-newlines format with embedded markdown (or commonmark) could fill the bill, be linted/formatted, and remain _pretty_ PR-able.
A schema can even include extra, validator-opaque metadata, like versionIntroduced, versionDeprecated, etc. currently buried in narrative, which can be used for documentation generation... and can in turn be validated by a meta-schema.
@bollwyvl DAP does generate the human-readable documentation specification.md using spec-generator.
Cool, spec-generator looks great!
@bollwyvl would you be willing to publish your generated.protocol.schema.json gist as a full-blown repository? That would help make it easier to track and maintain.
Yeah, we've been talking about that over on pygls... Though it's unclear
where it should actually live. Obviously wouldn't stay in notebooks, but
also can't promise we'd be shipping any packages any time soon.
On Fri, Feb 7, 2020, 15:16 Jason Axelson notifications@github.com wrote:
@bollwyvl https://github.com/bollwyvl would you be willing to publish
your generated.protocol.schema.json gist as a full-blown repository? That
would help make it easier to track and maintain.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/microsoft/language-server-protocol/issues/67?email_source=notifications&email_token=AAALCRCKX7FAMNOQQJJ2UC3RBW6SHA5CNFSM4CPIPIVKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELEOXNY#issuecomment-583592887,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAALCRDOESKWGCUA5EGL4FDRBW6SHANCNFSM4CPIPIVA
.
Personally I'd be fine with a repo. Doesn't need to be in a package for me.
@bollwyvl friendly ping :)
Are you still planning to move your code into a repo? If you aren't then in a few days (or when I get around to it) I'll create a repo to house it.
@axelson this is up: https://github.com/deathbeds/expectorate
It's got the pieces from the gist, but hasn't moved forward on much stuff. Again, not sure where it will go, but figured starting with something a bit more structured would be useful.
@bollwyvl Thanks for putting up the repo, will take a look shortly.
@dbaeumer can I politely suggest bumping the priority of this? ^^
The problem I see is that for each specific language, it's easier to just implement the thing manually, than to first implement a scheme, and than a generator on top.
For this reason, I don't think "community help" would work out perfectly in this case.
It seems to be the case where direct centralized action by de-facto protocol maintainers would work better :)
While updating to the latest spec, I came across multiple definitions of TextDocumentSyncOptions. This has been raised previously:
https://github.com/microsoft/language-server-protocol/issues/909
It was considered by-design, and a note was added explaining this. This is rather unfriendly to automatic conversion, as we can't really parse the english text. For now I'm assuming the last definition wins, but I'm sure that'll come back to bite me at some point.
@dbaeumer is there a full valid copy of all of these TypeScript definitions anywhere (eg. used by VS Code's client) that might be easier for us to parse than extracting individual blocks from here?
There's https://github.com/microsoft/vscode-languageserver-node/tree/master/protocol, but it has pretty complicated structure.
What would really help is a single .ts file without external references which defines all the types in the protocol (which would be just typescript types) and all the request-response (which would need some minor type-level DSL). This is essentially what is was originally proposed in this PR, I would thing that this approach is more convenient than JSON schema.
What would really help is a single
.tsfile without external references which defines all the types in the protocol (which would be just typescript types) and all the request-response (which would need some minor type-level DSL).
It still feels weird to have to parse TypeScript for this (instead of a format that is easily parseable in any language), but that would still be a huge step in the right direction. Most of my weird workarounds come from how the code is embedded in the markdown, duplicates, missing trailing commas, etc. which wouldn't be required if there was a single valid TS definition.
(I'd happily copy/paste all the definitions into a single file.. though I'm not sure of an easy plan to then keep it in-sync with the markdown..)
I still think that having a tool that converts the TS definitions in https://github.com/microsoft/vscode-languageserver-node/tree/master/protocol into a JSON schema is the right approach here. We could even use some TS decorators to help the tools to produce good JSON schema.
This is becoming more of a headache with a lot of churn for non-typescript implementations as we fumble along and get things subtly wrong. Is there any way we can push this further to get official support of some kind?
This would be a fantastic improvement. If it's at all helpful, @pjweinbgo wrote a generator for Go, which can be found here.
I totally agree but I simply don't have the bandwidth to look into this. I am open for changes to the TS files to make them easier to parse and convert to JSON schema but I would appreciate help from the community for the tool
FWIW I have generated json schema from https://github.com/eclipse/lsp4j/ available at: https://github.com/emacs-lsp/lsp-mode/blob/master/scripts/generated.protocol.schema.json
I wrote a generator we use for gopls that produces a Go version of the LSP types and stubs. It's in typescript and walks the parse tree looking for patterns, so it's filled with heuristics. One valuable feature is that it copies the relevant comments into the generated Go code. So if there's a json version of the LSP spec, it should include the comments. Another is that it knows that it is specific to a commit hash, so a json version should have some sort of version id that changes every time anything in the json changes. But because it looks at the released source code, it always up to date.
Leaving aside the fundamental incompatibility between the type systems for Go and Typescript, this approach is inherently fragile, as it depends on the vscode authors not making too many major revisions/reorganizations to their code.
In some ideal world, both the Go version and the Typescript version would be generated from the authoritative JSON source. Is that the hope?
Most helpful comment
@dbaeumer can I politely suggest bumping the priority of this? ^^
The problem I see is that for each specific language, it's easier to just implement the thing manually, than to first implement a scheme, and than a generator on top.
For this reason, I don't think "community help" would work out perfectly in this case.
It seems to be the case where direct centralized action by de-facto protocol maintainers would work better :)