Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fsac crashes when the file is empty #1091

Closed
augustfengd opened this issue Mar 27, 2023 · 7 comments · Fixed by #1100
Closed

fsac crashes when the file is empty #1091

augustfengd opened this issue Mar 27, 2023 · 7 comments · Fixed by #1100

Comments

@augustfengd
Copy link
Contributor

Hello!

I think there may be an edge case bug when the text file sent to the fsautocomplete is completely empty. The steps to reproduce on Emacs with lsp-mode is:

  • open or create a new project (dotnet new console -lang 'F#')
  • open Program.fs
  • delete entire buffer (C-x h backspace)
  • fsac crashes with the following error.
[21:17:43.180 ERR] [Startup] Start - LSP mode crashed
System.AggregateException: One or more errors occurred. (Index was outside the bounds of the array.)
 ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at FsAutoComplete.NamedText.FSharp.Compiler.Text.ISourceText.GetLineString(Int32 lineIndex) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete.Core/FileSystem.fs:line 333
   at FsAutoComplete.NamedText.GetText(Range m) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete.Core/FileSystem.fs:line 142
   at FsAutoComplete.NamedText.ModifyText(Range m, String text) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete.Core/FileSystem.fs:line 273
   at <StartupCode$fsautocomplete>.$FsAutoComplete.Lsp.evolvedFileContent@1305.Invoke(NamedText text, TextDocumentContentChangeEvent change) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs:line 1313
   at Microsoft.FSharp.Collections.ArrayModule.Fold[T,TState](FSharpFunc`2 folder, TState state, T[] array) in D:\a\_work\1\s\src\FSharp.Core\array.fs:line 1351
   at <StartupCode$fsautocomplete>.$FsAutoComplete.Lsp.FsAutoComplete-Lsp-IFSharpLspServer-TextDocumentDidChange@1289-15.Invoke(Unit unitVar) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs:line 1304
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvoke[T,TResult](AsyncActivation`1 ctxt, TResult result1, FSharpFunc`2 part2) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 510
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 148
   --- End of inner exception stack trace ---
   at Ionide.LanguageServerProtocol.Server.startWithSetup[client](FSharpFunc`2 setupRequestHandlings, Stream input, Stream output, FSharpFunc`2 clientCreator, FSharpFunc`2 customizeRpc) in /_//src/LanguageServerProtocol.fs:line 179
   at Ionide.LanguageServerProtocol.Server.start@270-2.Invoke(FSharpFunc`2 customizeRpc) in /_//src/LanguageServerProtocol.fs:line 270
   at FsAutoComplete.Lsp.FSharpLspServerModule.startCore(ToolsPath toolsPath, DirectoryInfo stateStorageDir, FSharpFunc`2 workspaceLoaderFactory) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs:line 2904
   at FsAutoComplete.Parser.lspFactory@156-1.Invoke(Unit unitVar0) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete/Parser.fs:line 156
   at FsAutoComplete.Lsp.FSharpLspServerModule.start(FSharpFunc`2 startCore) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs:line 2946

Process fsac stderr finished
@TheAngryByrd
Copy link
Member

Can you try with starting FSAC with --adaptive-lsp-server-enabled ?

@augustfengd
Copy link
Contributor Author

I'm on a different machine this morning, but still tried it and no bueno. What does adaptive do?

[07:30:30.829 ERR] [FsAutoComplete.Lsp.AdaptiveFSharpLspServer] checkUnusedOpens failed
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at FsAutoComplete.NamedText.FSharp.Compiler.Text.ISourceText.GetLineString(Int32 lineIndex) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete.Core/FileSystem.fs:line 323
   at FSharp.Compiler.EditorServices.UnusedOpens.filterSymbolUses@118.Invoke(FSharpSymbolUse su) in D:\a\_work\1\s\src\Compiler\Service\ServiceAnalysis.fs:line 148
   at Microsoft.FSharp.Collections.Internal.IEnumerator.next@248[T](FSharpFunc`2 f, IEnumerator`1 e, FSharpRef`1 started, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 252
   at Microsoft.FSharp.Collections.Internal.IEnumerator.filter@238.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 254
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at Microsoft.FSharp.Collections.SeqModule.ToArray[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 984
   at Microsoft.FSharp.Collections.ArrayModule.OfSeq[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\array.fs:line 1543
   at FSharp.Compiler.EditorServices.UnusedOpens.getUnusedOpens@299-1.Invoke(CancellationToken ct) in D:\a\_work\1\s\src\Compiler\Service\ServiceAnalysis.fs:line 300
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 528
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 148
[07:30:32.423 ERR] [FsAutoComplete.Lsp.AdaptiveFSharpLspServer] checkUnusedOpens failed
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at FsAutoComplete.NamedText.FSharp.Compiler.Text.ISourceText.GetLineString(Int32 lineIndex) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete.Core/FileSystem.fs:line 323
   at FSharp.Compiler.EditorServices.UnusedOpens.filterSymbolUses@118.Invoke(FSharpSymbolUse su) in D:\a\_work\1\s\src\Compiler\Service\ServiceAnalysis.fs:line 148
   at Microsoft.FSharp.Collections.Internal.IEnumerator.next@248[T](FSharpFunc`2 f, IEnumerator`1 e, FSharpRef`1 started, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 252
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at Microsoft.FSharp.Collections.SeqModule.ToArray[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 984
   at Microsoft.FSharp.Collections.ArrayModule.OfSeq[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\array.fs:line 1543
   at FSharp.Compiler.EditorServices.UnusedOpens.getUnusedOpens@299-1.Invoke(CancellationToken ct) in D:\a\_work\1\s\src\Compiler\Service\ServiceAnalysis.fs:line 300
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 528
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 148
[07:30:32.473 ERR] [FsAutoComplete.Lsp.AdaptiveFSharpLspServer] checkUnusedOpens failed
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at FsAutoComplete.NamedText.FSharp.Compiler.Text.ISourceText.GetLineString(Int32 lineIndex) in /home/runner/work/FsAutoComplete/FsAutoComplete/src/FsAutoComplete.Core/FileSystem.fs:line 323
   at FSharp.Compiler.EditorServices.UnusedOpens.filterSymbolUses@118.Invoke(FSharpSymbolUse su) in D:\a\_work\1\s\src\Compiler\Service\ServiceAnalysis.fs:line 148
   at Microsoft.FSharp.Collections.Internal.IEnumerator.next@248[T](FSharpFunc`2 f, IEnumerator`1 e, FSharpRef`1 started, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 252
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at Microsoft.FSharp.Collections.SeqModule.ToArray[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 984
   at Microsoft.FSharp.Collections.ArrayModule.OfSeq[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\array.fs:line 1543
   at FSharp.Compiler.EditorServices.UnusedOpens.getUnusedOpens@299-1.Invoke(CancellationToken ct) in D:\a\_work\1\s\src\Compiler\Service\ServiceAnalysis.fs:line 300
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 528
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\FSharp.Core\async.fs:line 148

@TheAngryByrd
Copy link
Member

but still tried it and no bueno.

This doesn't look like an crash though. Just some exceptions for analyzers. While still annoying, it's not crashing.

What does adaptive do?

Newer implementation of the LSP server using F# Data Adaptive to help keep track of dependencies.

@augustfengd
Copy link
Contributor Author

augustfengd commented Mar 27, 2023

Actually, I just realized that it doesn't crash immediately when the buffer is empty, but after I input something in the buffer. I think this has something to do with the lack of a new line in the buffer.

According to POSIX, a text file must end with a newline so an empty buffer like this is not considered a valid text file, but it would still be nice to handle empty buffers.

I tried debugging this code-wise yesterday but didn't get very far.

Here's a recording of the issue if it helps:

fsautocomplete-bug.mov

@augustfengd
Copy link
Contributor Author

OK! Had my first breakthrough, seems FSAC crashes on textDocument/didChange when the existing content is the empty string.

I patched the FsAutoComplete.Lsp.fs file locally with this and it's not crashing anymore.

            match change.Range with
            | None -> // replace entire content
              NamedText(filePath, change.Text)
+           | Some rangeToReplace
+               when rangeToReplace.Start.Character = 0 && rangeToReplace.Start.Line = 0 &&
+                    rangeToReplace.End.Character = 0 && rangeToReplace.End.Line = 0 ->
+             NamedText(filePath, change.Text)
            | Some rangeToReplace ->

I still get some warning messages about positions out of range, most likely from the server's other capabilities though.

@baronfel
Copy link
Contributor

@augustfengd that change makes good sense - if you sent it up in a PR (as well as a parallel change to the same login in AdaptiveFSharpLspServer.fs please!) we'd take it in a heartbeat :)

@augustfengd
Copy link
Contributor Author

Hey! :) I had a look at the AdaptiveFSharpLspServer.fs and the TextDocumentDidChange method looked quite different so I double-checked and it doesn't crash actually. @TheAngryByrd you were right 😅 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants