ionide / ionide-vscode-fsharp

VS Code plugin for F# development
http://ionide.io
MIT License
865 stars 280 forks source link

Request textDocument/formatting failed #1496

Closed JonCanning closed 2 years ago

JonCanning commented 3 years ago

Format Document command yields this error in the Output console

[Error - 2:03:34 PM] Request textDocument/formatting failed.
  Message: Newtonsoft.Json.JsonSerializationException: Cannot set value onto extension data member 'AdditionalData'. The extension data collection is null and it cannot be set.
   at Newtonsoft.Json.Serialization.DefaultContractResolver.<>c__DisplayClass45_1.<SetExtensionDataDelegates>b__0(Object o, String key, Object value)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
   at LanguageServerProtocol.Server.requestHandling@2513.Invoke(server lspServer, FSharpOption`1 paramsToken) in D:\a\ionide-vscode-fsharp\ionide-vscode-fsharp\paket-files\github.com\fsharp\FsAutoComplete\src\LanguageServerProtocol\LanguageServerProtocol.fs:line 2546
  Code: -32700 
open-collective-bot[bot] commented 3 years ago

Hey @JonCanning :wave:,

Thank you for opening an issue. We will get back to you as soon as we can. Also, check out our OpenCollective and consider backing us.

https://opencollective.com/ionide

PS.: We offer backer support for all backers. Don't forget to add backer label when you start backing us :smile:

michael-mwp commented 3 years ago

I am experiencing this too since v5.3.0 was released.

baronfel commented 3 years ago

Can either of you please provide a sample fsx file or zipped project that this can be reproduced on?

JonCanning commented 3 years ago

It happens to me with an empty fsx file

baronfel commented 3 years ago

Thanks, that helps a lot

baronfel commented 3 years ago

I can't replicate on my machine using ionide 5.3.2 on macos on .net sdk 5.0.102. Here's the log I see with the following settings set when I invoke 'format document' on an empty (or even full!) script file:

    "FSharp.verboseLogging": false,
    "FSharp.trace.server": "verbose"
[Trace - 5:40:10 PM] Sending request 'textDocument/formatting - (20)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/chethusk/oss/scratch/script.fsx"
    },
    "options": {
        "tabSize": 4,
        "insertSpaces": true
    }
}

[17:40:10.247 WRN] [Fantomas] No fantomas configuration found for file '/Users/chethusk/oss/scratch/script.fsx' or parent directories. Using the default configuration.
[Trace - 5:40:10 PM] Received response 'textDocument/formatting - (20)' in 126ms.
Result: [
    {
        "range": {
            "start": {
                "line": 0,
                "character": 0
            },
            "end": {
                "line": 0,
                "character": 0
            }
        },
        "newText": ""
    }
]

Can you provide me with these calls back and forth on your machine? Otherwise I don't know how to help you.

JonCanning commented 3 years ago
[Trace - 8:54:00 AM] Sending request 'textDocument/formatting - (168)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jon/dev/Property/output/empty.fsx"
    },
    "options": {
        "tabSize": 2,
        "insertSpaces": true,
        "trimTrailingWhitespace": true,
        "trimFinalNewlines": true
    }
}

[Trace - 8:54:00 AM] Received response 'textDocument/formatting - (168)' in 2ms. Request failed: Newtonsoft.Json.JsonSerializationException: Cannot set value onto extension data member 'AdditionalData'. The extension data collection is null and it cannot be set.
   at Newtonsoft.Json.Serialization.DefaultContractResolver.<>c__DisplayClass45_1.<SetExtensionDataDelegates>b__0(Object o, String key, Object value)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
   at LanguageServerProtocol.Server.requestHandling@2513.Invoke(server lspServer, FSharpOption`1 paramsToken) in D:\a\ionide-vscode-fsharp\ionide-vscode-fsharp\paket-files\github.com\fsharp\FsAutoComplete\src\LanguageServerProtocol\LanguageServerProtocol.fs:line 2546 (-32700).
[Error - 8:54:00 AM] Request textDocument/formatting failed.
  Message: Newtonsoft.Json.JsonSerializationException: Cannot set value onto extension data member 'AdditionalData'. The extension data collection is null and it cannot be set.
   at Newtonsoft.Json.Serialization.DefaultContractResolver.<>c__DisplayClass45_1.<SetExtensionDataDelegates>b__0(Object o, String key, Object value)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
   at LanguageServerProtocol.Server.requestHandling@2513.Invoke(server lspServer, FSharpOption`1 paramsToken) in D:\a\ionide-vscode-fsharp\ionide-vscode-fsharp\paket-files\github.com\fsharp\FsAutoComplete\src\LanguageServerProtocol\LanguageServerProtocol.fs:line 2546
  Code: -32700 
michael-mwp commented 3 years ago

Developers in my team are experiencing the same. We're running Ionide 5.3.2 VSCode 1.53.1 on Windows 10 .NET SDK 5.0.102

[Trace - 09:20:45] Sending request 'textDocument/formatting - (3570)'.
Params: {
    "textDocument": {
        "uri": "******"
    },
    "options": {
        "tabSize": 4,
        "insertSpaces": true,
        "trimTrailingWhitespace": true,
        "trimFinalNewlines": true
    }
}

[Trace - 09:20:45] Received response 'textDocument/formatting - (3570)' in 1ms. Request failed: Newtonsoft.Json.JsonSerializationException: Cannot set value onto extension data member 'AdditionalData'. The extension data collection is null and it cannot be set.
   at Newtonsoft.Json.Serialization.DefaultContractResolver.<>c__DisplayClass45_1.<SetExtensionDataDelegates>b__0(Object o, String key, Object value)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
   at LanguageServerProtocol.Server.requestHandling@2513.Invoke(server lspServer, FSharpOption`1 paramsToken) in D:\a\ionide-vscode-fsharp\ionide-vscode-fsharp\paket-files\github.com\fsharp\FsAutoComplete\src\LanguageServerProtocol\LanguageServerProtocol.fs:line 2546 (-32700).
[Error - 09:20:45] Request textDocument/formatting failed.
  Message: Newtonsoft.Json.JsonSerializationException: Cannot set value onto extension data member 'AdditionalData'. The extension data collection is null and it cannot be set.
   at Newtonsoft.Json.Serialization.DefaultContractResolver.<>c__DisplayClass45_1.<SetExtensionDataDelegates>b__0(Object o, String key, Object value)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
   at LanguageServerProtocol.Server.requestHandling@2513.Invoke(server lspServer, FSharpOption`1 paramsToken) in D:\a\ionide-vscode-fsharp\ionide-vscode-fsharp\paket-files\github.com\fsharp\FsAutoComplete\src\LanguageServerProtocol\LanguageServerProtocol.fs:line 2546
  Code: -32700 
JonCanning commented 3 years ago

Have tracked it down to having these enabled:

"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
michael-mwp commented 3 years ago

I can confirm removing those VSCode settings does provide a workaround.

JonCanning commented 3 years ago

Seems like these settings are now unnecessary since my editor is still trimming whitespace and lines. If this is the same for you @michael-i2o then I'll close this

baronfel commented 3 years ago

Many thanks you two. Due to your discussion I was able to easily trace this to our implementation of Newtonsoft.Json AdditionalData (https://github.com/fsharp/fsautocomplete/blob/master/src/LanguageServerProtocol/LanguageServerProtocol.fs#L1175), which doesn't seem to be working with records.

That explains why removing the properties we didn't explicitly have mapped caused this to start working.

It's worth noting that since we use fantomas for formatting, if you have a .editorconfig in your repo it will use those settings around newlines, whitespace, etc to format the document.

michael-mwp commented 3 years ago

The global files.trimTrailingWhitespace setting applies to all file types and not just F# files, so unfortunately requiring users to remove it or set to false for Ionide F# linting to work isn't going to be acceptable for many users.

My team has it set to ensure code and data files for many different languages/formats have trailing whitespace trimmed when saving a file. Instead of setting a global setting we could instead set it per file type, but I don't think a VSCode extension should put a requirement on the use/state of VSCode global settings.

Is the real issue here that the Ionide implementation of Newtonsoft.Json AdditionalData doesn't support records, or an issue in another package? Sorry, I quite didn't follow your explaination @baronfel

baronfel commented 3 years ago

Oh I don't disagree at all, just suggesting workarounds for the current state. Really we need to do a fix in FSAC for the additional data field. That may mean removing it, that may mean changing that structure to a class for better interop with Newtonsoft.Json, or other resolutions.

michael-mwp commented 3 years ago

Removing or moving those global settings to specific file type settings is a painless workaround 👍

colelawrence commented 3 years ago

A couple of the suggestions here didn't work out for me, but putting the following settings into my workspace settings.json resolved the error:

{
  "[fsharp]": {
    "files.insertFinalNewline": false,
    "editor.defaultFormatter": "Ionide.Ionide-fsharp"
  },
}

editor.defaultFormatter isn't entirely necessary.

MangelMaxime commented 2 years ago

With the new Fantomas service, is there still something to be done for this issue?

Krzysztof-Cieslak commented 2 years ago

I don't think Fantmas service helped here in any way (the bug was in our LSP layer), but maybe this got accidentally fixed with all the improvements to our LPS library? CC: @baronfel

baronfel commented 2 years ago

Correct - this was fixed in the underlying library.