Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Changelog

## [Unreleased]
## [0.50.1] - 2022-03-12

### Fixed

* [Fix textDocument/publishDiagnostics sometimes not getting sent](https://github.com/fsharp/FsAutoComplete/pull/887) (Thanks @Booksbaum!)
* [Fix completions in the middle of lines](https://github.com/fsharp/FsAutoComplete/pull/892)

## [0.50.0] - 2022-01-23

Expand Down
2 changes: 1 addition & 1 deletion paket.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ NUGET
Argu (5.2)
FSharp.Core (>= 4.3.2)
System.Configuration.ConfigurationManager (>= 4.4)
CliWrap (3.4)
CliWrap (3.4.1)
Microsoft.Bcl.AsyncInterfaces (>= 6.0) - restriction: || (&& (== net5.0) (>= net461)) (&& (== net5.0) (< netstandard2.1)) (== netstandard2.0)
System.Buffers (>= 4.5.1) - restriction: || (&& (== net5.0) (>= net461)) (&& (== net5.0) (< netstandard2.1)) (== netstandard2.0)
System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net5.0) (>= net461)) (&& (== net5.0) (< netstandard2.1)) (== netstandard2.0)
Expand Down
2 changes: 1 addition & 1 deletion src/FsAutoComplete.BackgroundServices/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ type BackgroundServiceServer(state: State, client: FsacClient) =
let file = Utils.normalizePath p.File.FilePath

let vf =
{ Lines = SourceText.ofString p.Content
{ Lines = NamedText(file, p.Content)
Touched = DateTime.Now
Version = Some p.Version }
state.Files.AddOrUpdate(file, (fun _ -> vf),( fun _ _ -> vf) ) |> ignore
Expand Down
1 change: 1 addition & 0 deletions src/FsAutoComplete.BackgroundServices/paket.references
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ FSharp.UMX
Microsoft.NETFramework.ReferenceAssemblies
Ionide.LanguageServerProtocol
Ionide.KeepAChangelog.Tasks
FsToolkit.ErrorHandling
17 changes: 9 additions & 8 deletions src/FsAutoComplete.Core/CodeGeneration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@ open FSharp.Compiler.Text
open FSharp.Compiler.Symbols
open FSharp.Compiler.Tokenization
open FSharp.Compiler.CodeAnalysis
open FsToolkit.ErrorHandling

[<Measure>] type Line0
[<Measure>] type Line1

type CodeGenerationService(checker : FSharpCompilerServiceChecker, state : State) =
member x.TokenizeLine(fileName, i) =
match state.TryGetFileCheckerOptionsWithLines fileName with
| ResultOrString.Error _ -> None
| ResultOrString.Ok (opts, text) ->
try
let line = text.GetLineString (i - 1)
Lexer.tokenizeLine [||] line |> Some
with
| _ -> None
option {
let! text = state.TryGetFileSource fileName |> Option.ofResult
try
let! line = text.GetLine (Position.mkPos (i - 1) 0)
return Lexer.tokenizeLine [||] line
with
| _ -> return! None
}

member x.GetSymbolAtPosition(fileName, pos: Position) =
match state.TryGetFileCheckerOptionsWithLinesAndLineStr(fileName, pos) with
Expand Down
85 changes: 36 additions & 49 deletions src/FsAutoComplete.Core/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type CoreResponse<'a> =

[<RequireQualifiedAccess>]
type FormatDocumentResponse =
| Formatted of source: ISourceText * formatted: string
| Formatted of source: NamedText * formatted: string
| UnChanged
| Ignored
| ToolNotPresent
Expand Down Expand Up @@ -376,7 +376,7 @@ type Commands
| Some f -> Some(f.Lines)
| None when File.Exists(UMX.untag file) ->
let ctn = File.ReadAllText(UMX.untag file)
let text = SourceText.ofString ctn
let text = NamedText(file, ctn)

state.Files.[file] <-
{ Touched = DateTime.Now
Expand Down Expand Up @@ -425,11 +425,9 @@ type Commands
GetLineText1 = fun i -> lines.GetLineString(i - 1) }

let calculateNamespaceInsert (decl: DeclarationListItem) (pos: Position) getLine : CompletionNamespaceInsert option =
let getLine i =
try
getLine i
with
| _ -> ""
let getLine (p: Position) =
getLine p
|> Option.defaultValue ""

let idents = decl.FullName.Split '.'

Expand All @@ -441,13 +439,12 @@ type Commands
|> Option.map (fun ic ->
//TODO: unite with `CodeFix/ResolveNamespace`
//TODO: Handle Nearest AND TopLevel. Currently it's just Nearest (vs. ResolveNamespace -> TopLevel) (#789)
let l, c = ic.Pos.Line, ic.Pos.Column

let detectIndentation (line: string) =
line |> Seq.takeWhile ((=) ' ') |> Seq.length

// adjust line
let l =
let pos =
match ic.ScopeKind with
| ScopeKind.Namespace ->
// for namespace `open` isn't created close at namespace,
Expand All @@ -456,33 +453,31 @@ type Commands
// this only happens when there are no other `open`

// from insert position go up until first open OR namespace
seq { l - 1 .. -1 .. 0 }
ic.Pos.LinesToBeginning()
|> Seq.tryFind (fun l ->
let lineStr = getLine l
// namespace MUST be top level -> no indentation
lineStr.StartsWith "namespace ")
|> function
// move to the next line below "namespace"
| Some l -> l + 1
| None -> l
| _ -> l
| Some l -> l.IncLine()
| None -> ic.Pos
| _ -> ic.Pos

// adjust column
let c =
match l, c with
| 0, c -> c
| l, 0 ->
let prev = getLine (l - 1)
let pos =
match pos with
| Pos(0, c) -> pos
| Pos(l, 0) ->
let prev = getLine (pos.DecLine())
let indentation = detectIndentation prev

if indentation <> 0 then
// happens when there are already other `open`s
indentation
Position.mkPos l indentation
else
0
| _, c -> c

let pos = Position.mkPos l c
pos
| Pos(_, c) -> pos

{ Namespace = n
Position = pos
Expand Down Expand Up @@ -561,7 +556,7 @@ type Commands

member __.LastCheckResult = lastCheckResult

member __.SetFileContent(file: string<LocalPath>, lines: ISourceText, version, tfmIfScript) =
member __.SetFileContent(file: string<LocalPath>, lines: NamedText, version, tfmIfScript) =
state.AddFileText(file, lines, version)

let payload =
Expand Down Expand Up @@ -738,7 +733,7 @@ type Commands

member x.TryGetFileVersion = state.TryGetFileVersion

member x.Parse file (text: ISourceText) version (isSdkScript: bool option) =
member x.Parse file (text: NamedText) version (isSdkScript: bool option) =
let tmf =
isSdkScript
|> Option.map (fun n ->
Expand Down Expand Up @@ -796,7 +791,7 @@ type Commands
)

let hash =
text.Lines()
text.Lines
|> Array.filter (fun n ->
n.StartsWith "#r"
|| n.StartsWith "#load"
Expand Down Expand Up @@ -905,8 +900,6 @@ type Commands
match source with
| None -> return CoreResponse.ErrorRes(sprintf "No help text available for symbol '%s'" sym)
| Some source ->
let getSource = fun i -> source.GetLineString(i - 1)

let tip =
match state.HelpText.TryFind sym with
| Some tip -> tip
Expand All @@ -917,7 +910,7 @@ type Commands

let n =
match state.CompletionNamespaceInsert.TryFind sym with
| None -> calculateNamespaceInsert decl pos getSource
| None -> calculateNamespaceInsert decl pos source.GetLine
| Some s -> Some s

return CoreResponse.Res(HelpText.Full(sym, tip, n))
Expand All @@ -933,7 +926,7 @@ type Commands
(tyRes: ParseAndCheckResults)
(pos: Position)
lineStr
(lines: ISourceText)
(lines: NamedText)
(fileName: string<LocalPath>)
filter
includeKeywords
Expand All @@ -951,7 +944,6 @@ type Commands
match res with
| Some (decls, residue, shouldKeywords) ->
let declName (d: DeclarationListItem) = d.Name
let getLine = fun i -> lines.GetLineString(i - 1)

//Init cache for current list
state.Declarations.Clear()
Expand All @@ -960,7 +952,7 @@ type Commands
state.CurrentAST <- Some tyRes.GetAST

//Fill cache for current list
do fillHelpTextInTheBackground decls pos fileName getLine
do fillHelpTextInTheBackground decls pos fileName lines.GetLine

// Send the first help text without being requested.
// This allows it to be displayed immediately in the editor.
Expand Down Expand Up @@ -1079,7 +1071,7 @@ type Commands
(
tyRes: ParseAndCheckResults,
pos: Position,
lines: ISourceText,
lines: NamedText,
triggerChar,
possibleSessionKind
) =
Expand Down Expand Up @@ -1374,7 +1366,7 @@ type Commands
match tyResOpt with
| None -> ()
| Some tyRes ->
let getSourceLine lineNo = source.GetLineString(lineNo - 1)
let getSourceLine lineNo = (source :> ISourceText).GetLineString(lineNo - 1)
let! simplified = SimplifyNames.getSimplifiableNames (tyRes.GetCheckResults, getSourceLine)
let simplified = Array.ofSeq simplified
notify.Trigger(NotificationEvent.SimplifyNames(file, simplified))
Expand All @@ -1390,7 +1382,7 @@ type Commands
match checker.TryGetRecentCheckResultsForFile(file, opts, source) with
| None -> return ()
| Some tyRes ->
let! unused = UnusedOpens.getUnusedOpens (tyRes.GetCheckResults, (fun i -> source.GetLineString(i - 1)))
let! unused = UnusedOpens.getUnusedOpens (tyRes.GetCheckResults, (fun i -> (source: ISourceText).GetLineString(i - 1)))
notify.Trigger(NotificationEvent.UnusedOpens(file, (unused |> List.toArray)))

}
Expand Down Expand Up @@ -1543,21 +1535,16 @@ type Commands
let! contents = state.TryGetFileSource tyRes.FileName

let getGenerics line (token: FSharpTokenInfo) =
let lineStr = contents.GetLineString line
option {
let! lineStr = contents.GetLine (Position.mkPos line 0)

let res =
tyRes.TryGetToolTip(Position.fromZ line token.RightColumn) lineStr
let! tip =
tyRes.TryGetToolTip(Position.fromZ line token.RightColumn) lineStr
|> Option.ofResult

match res with
| Ok tip -> TipFormatter.extractGenericParameters tip
| _ ->
commandsLogger.info (
Log.setMessage "ParameterHints - No tooltips for token: '{token}'\n Line: \n{line}"
>> Log.addContextDestructured "token" token
>> Log.addContextDestructured "line" lineStr
)

[]
return TipFormatter.extractGenericParameters tip
}
|> Option.defaultValue []

let areTokensCommentOrWhitespace (tokens: FSharpTokenInfo list) =
tokens
Expand Down Expand Up @@ -1593,7 +1580,7 @@ type Commands
| false, None -> currentIndex, false, acc

let hints =
Array.init (contents.GetLineCount()) (fun line -> contents.GetLineString line)
Array.init ((contents: ISourceText).GetLineCount()) (fun line -> (contents: ISourceText).GetLineString line)
|> Array.map (Lexer.tokenizeLine [||])
|> Array.mapi (fun currentIndex currentTokens -> currentIndex, currentTokens)
|> Array.fold folder (0, false, [])
Expand Down
4 changes: 2 additions & 2 deletions src/FsAutoComplete.Core/CompilerServiceInterface.fs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ type FSharpCompilerServiceChecker(backgroundServiceEnabled, hasAnalyzers) =
let path = UMX.untag fn
checker.ParseFile(path, source, fpo)

member __.ParseAndCheckFileInProject(filePath: string<LocalPath>, version, source, options) =
member __.ParseAndCheckFileInProject(filePath: string<LocalPath>, version, source: NamedText, options) =
async {
let opName = sprintf "ParseAndCheckFileInProject - %A" filePath
checkerLogger.info
Expand Down Expand Up @@ -329,7 +329,7 @@ type FSharpCompilerServiceChecker(backgroundServiceEnabled, hasAnalyzers) =
| ex -> return ResultOrString.Error(ex.ToString())
}

member __.TryGetRecentCheckResultsForFile(file: string<LocalPath>, options, source) =
member __.TryGetRecentCheckResultsForFile(file: string<LocalPath>, options, source: NamedText) =
let opName = sprintf "TryGetRecentCheckResultsForFile - %A" file

checkerLogger.info
Expand Down
48 changes: 2 additions & 46 deletions src/FsAutoComplete.Core/FCSPatches.fs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type FSharpParseFileResults with
function | SynExpr.App(ExprAtomicFlag.NonAtomic, false, SynExpr.App(ExprAtomicFlag.NonAtomic, true, Ident "op_EqualsGreater", actualParamListExpr, _), actualLambdaBodyExpr, _) -> Some (actualParamListExpr, actualLambdaBodyExpr)
| _ -> None


let visitor = {
new SyntaxVisitorBase<_>() with
member _.VisitExpr(_, _, defaultTraverse, expr) =
Expand Down Expand Up @@ -277,7 +277,7 @@ type FSharpParseFileResults with
traverseSynExpr expr
|> Option.map (fun expr -> expr)


SyntaxTraversal.Traverse(pos, scope.ParseTree, { new SyntaxVisitorBase<_>() with
member _.VisitExpr(_, traverseSynExpr, defaultTraverse, expr) =
match expr with
Expand All @@ -304,50 +304,6 @@ type FSharpParseFileResults with
None
| _ -> defaultTraverse expr })

member scope.IsTypeAnnotationGivenAtPositionPatched pos =
let result =
SyntaxTraversal.Traverse(pos, scope.ParseTree, { new SyntaxVisitorBase<_>() with
member _.VisitExpr(_path, _traverseSynExpr, defaultTraverse, expr) =
match expr with
| SynExpr.Typed (_expr, _typeExpr, range) when Position.posEq range.Start pos ->
Some range
| _ -> defaultTraverse expr

override _.VisitSimplePats(_, pats) =
match pats with
| [] -> None
| _ ->
let exprFunc pat =
match pat with
| SynSimplePat.Typed (_pat, _targetExpr, range) when Position.posEq range.Start pos ->
Some range
| _ ->
None

pats |> List.tryPick exprFunc

override _.VisitPat(_, defaultTraverse, pat) =
match pat with
| SynPat.Typed (_pat, _targetType, range) when Position.posEq range.Start pos ->
Some range
| _ -> defaultTraverse pat })
result.IsSome

member scope.IsBindingALambdaAtPositionPatched pos =
let result =
SyntaxTraversal.Traverse(pos, scope.ParseTree, { new SyntaxVisitorBase<_>() with
member _.VisitExpr(_path, _traverseSynExpr, defaultTraverse, expr) =
defaultTraverse expr

override _.VisitBinding(_, defaultTraverse, binding) =
match binding with
| SynBinding(_, _, _, _, _, _, _, _, _, expr, range, _) when Position.posEq range.Start pos ->
match expr with
| SynExpr.Lambda _ -> Some range
| _ -> None
| _ -> defaultTraverse binding })
result.IsSome

module SyntaxTreeOps =
open FSharp.Compiler.Syntax
let rec synExprContainsError inpExpr =
Expand Down
Loading