redhat-developer / lsp4ij

LSP Client for IntelliJ
Eclipse Public License 2.0
85 stars 16 forks source link

`null` gets stripped from user-defined language server configurations #465

Open bzoracler opened 3 weeks ago

bzoracler commented 3 weeks ago

I'm setting configurations through the user-defined language server UI, and find that properties with values explicitly set as null are being stripped before the server receives them:

image

[Trace - 15:45:59] Sending request 'initialize - (1)'.
Params: {
  <...>,
  "initializationOptions": {
    "field2": "name",
    "field3": "nullaaaa"
  },
[Trace - 15:50:03] Sending notification 'workspace/didChangeConfiguration'
Params: {
  "settings": {
    "fieldB": "name"
  }
}

When I use the server to request the options/settings from the client, the fields which were set to null are now simply missing.

I expect preservation of fields set to null when sent from the client to the server1. The configuration object that's being retrieved from the UI2 shows that null is actually present in the client configuration object before being sent to the server, so something must be happening after reading the configuration.


  1. According to the language server specification, the types of initializationOptions and return value of configuration requests are both LSPAny, which is a type union including LSPObject and null. LSPObject is defined as:

    type LSPObject = { [key: string]: LSPAny };

    So, LSPObjects are allowed to have string keys and null values.

  2. Using the following modification of com.redhat.devtools.lsp4ij.server.definition.launching.UserDefinedLanguageServerDefinition:

    ...
    + import com.google.gson.JsonElement;
      import com.google.gson.JsonParser;
    ...
      public Object getLanguageServerConfiguration() {
              if (configuration == null && configurationContent != null && !configurationContent.isBlank()) {
                  try {
                      configuration = JsonParser.parseReader(new StringReader(configurationContent));
                  } catch (Exception e) {
                      LOGGER.error("Error while parsing JSON configuration for the language server '" + getId() + "'", e);
                  }
              }
    +         LOGGER.error("CONFIGURATION IS: " + ((JsonElement)configuration).toString());
              return configuration;
      }

    IDE Logs:

    SEVERE - com.redhat.devtools.lsp4ij.server.definition.launching.UserDefinedLanguageServerDefinition - CONFIGURATION IS: {"fieldA":null,"fieldB":"name"}
angelozerr commented 3 weeks ago

Indeed that's strange. Is there any chance that you investigate more the problem?

bzoracler commented 3 weeks ago

The problem is in com.redhat.devtools.lsp4ij.console.explorer.TracingMessageConsumer, in the locations where it calls MessageJsonHandler.toString(...).

org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler#toString uses a default Gson instance which doesn't serialise nulls.

I made a temporary patch using a Gson instance which turns on null serialisation, and the nulls started appearing in the traces.

angelozerr commented 2 weeks ago

For configuration I undestand that it is better to see null fields, but for other lsp request responses message like completion , showing null fields are not interesting, will grow up the lsp message in the console which will polluate the lsp console.