{"action":"reopened","issue":{"url":"https://api.github.com/repos/Microsoft/language-server-protocol/issues/87","repository_url":"https://api.github.com/repos/Microsoft/language-server-protocol","labels_url":"https://api.github.com/repos/Microsoft/language-server-protocol/issues/87/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/language-server-protocol/issues/87/comments","events_url":"https://api.github.com/repos/Microsoft/language-server-protocol/issues/87/events","html_url":"https://github.com/Microsoft/language-server-protocol/issues/87","id":181695426,"number":87,"title":"Simplify protocol with regards to optional fields vs nullable fields.","user":{"login":"bruno-medeiros","id":4324232,"avatar_url":"https://avatars.githubusercontent.com/u/4324232?v=3","gravatar_id":"","url":"https://api.github.com/users/bruno-medeiros","html_url":"https://github.com/bruno-medeiros","followers_url":"https://api.github.com/users/bruno-medeiros/followers","following_url":"https://api.github.com/users/bruno-medeiros/following{/other_user}","gists_url":"https://api.github.com/users/bruno-medeiros/gists{/gist_id}","starred_url":"https://api.github.com/users/bruno-medeiros/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bruno-medeiros/subscriptions","organizations_url":"https://api.github.com/users/bruno-medeiros/orgs","repos_url":"https://api.github.com/users/bruno-medeiros/repos","events_url":"https://api.github.com/users/bruno-medeiros/events{/privacy}","received_events_url":"https://api.github.com/users/bruno-medeiros/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2016-10-07T15:15:38Z","updated_at":"2016-10-14T14:13:10Z","closed_at":null,"body":"From my understanding, in the protocol, a field marked as \"?\" is optional. If it's not marked as optional, the *key* must be present, however, the value can still be null. This duality is confusing and makes it harder to undertand the protocol. Let's take `InitializeParams` as an example:\r\n\r\n```typescript\r\ninterface InitializeParams {\r\n\t/**\r\n\t * The process Id of the parent process that started\r\n\t * the server.\r\n\t */\r\n\tprocessId: number;\r\n\r\n\t/**\r\n\t * The rootPath of the workspace. Is null\r\n\t * if no folder is open.\r\n\t */\r\n\trootPath: string;\r\n\r\n\t/**\r\n\t * User provided initialization options.\r\n\t */\r\n\tinitializationOptions?: any;\r\n\r\n\t/**\r\n\t * The capabilities provided by the client (editor)\r\n\t */\r\n\tcapabilities: ClientCapabilities;\r\n}\r\n```\r\n\r\nWe can clearly see that the the `initializationOptions` key is optional, but `rootPath` and `processId` are not. However, `rootPath` can be null, as the documentation specifies. But what about `processId`? Can it be null? It's not clear from the spec. I'd imagine it shouldn't be null, if it's not explicitly mentioned in the documentation. Yet I've tried out LSP4J and it sends `processId` as null... Who is right?\r\n\r\nI propose that any field that can be null should be marked as optional (with \"?\"). Such that effectively, LSP states there is no semantic difference between a field that is missing (no key at all), and a field with key present, but with null value. This would eliminate ambiguities such as the example above.\r\n\r\nThis semantic distinction is even more important for languages such as Rust which don't have nullable types. (I'm writing an LSP SDK for Rust, and just realized this ambiguity will be a major pain) \r\n"}}
{"actor":{"display_login":"dbaeumer"}}