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

Refactor AdaptiveServerState.forceFindOpenFileOrRead #1208

Closed
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
8 changes: 7 additions & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@
]
},
"fantomas": {
"version": "6.2.2",
"version": "6.2.3",
"commands": [
"fantomas"
]
},
"fsharp-analyzers": {
"version": "0.20.2",
"commands": [
"fsharp-analyzers"
]
}
}
}
25 changes: 21 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ jobs:
run: dotnet --info

- name: Restore tools
run: |
# can't do a tool restore here due to an 8.0.100 rc2 bug - this is fixed in GA so can go back to
# dotnet tool restore then.
dotnet tool install paket --version 8.0.0-alpha002 && dotnet tool install fantomas --version 6.2.2 && dotnet paket restore
run: dotnet tool restore

- name: Check format
run: dotnet build -t:CheckFormat
Expand All @@ -107,3 +104,23 @@ jobs:
env:
BuildNet7: ${{ matrix.build_net7 }}
BuildNet8: ${{ matrix.build_net8 }}

analyze:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Setup .NET
uses: actions/setup-dotnet@v3

- name: Restore tools
run: dotnet tool restore

- name: Run analyzers
run: dotnet build -t:AnalyzeSolution -p:TargetFramework=net6.0

- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: analysisreports
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ test/FsAutoComplete.Tests.Lsp/TestResults/

.tool-versions
BenchmarkDotNet.Artifacts/

*.sarif
5 changes: 5 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@
</PropertyGroup>
</Target>

<PropertyGroup>
<SarifOutput Condition="$(SarifOutput) == ''">./</SarifOutput>
<CodeRoot Condition="$(CodeRoot) == ''">.</CodeRoot>
<FSharpAnalyzersOtherFlags>--analyzers-path &quot;$(PkgIonide_Analyzers)/analyzers/dotnet/fs&quot; --code-root $(CodeRoot) --report &quot;$(SarifOutput)/$(MSBuildProjectName)-$(TargetFramework).sarif&quot; --verbose</FSharpAnalyzersOtherFlags>
</PropertyGroup>

</Project>
16 changes: 16 additions & 0 deletions Directory.Solution.targets
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,20 @@
<Target Name="CheckFormat">
<Exec Command="dotnet fantomas --check @(FormatInputs, ' ') " />
</Target>

<ItemGroup>
<ProjectsToAnalyze Include="src/**/*.fsproj" />
</ItemGroup>

<Target Name="AnalyzeSolution">
<PropertyGroup>
<CodeRoot>$(SolutionDir)</CodeRoot>
<SarifOutput>$(SolutionDir)/analysisreports</SarifOutput>
</PropertyGroup>
<MSBuild
Projects="@(ProjectsToAnalyze)"
Targets="AnalyzeFSharpProject"
Properties="CodeRoot=$(CodeRoot);SarifOutput=$(SarifOutput)" />
</Target>

</Project>
4 changes: 4 additions & 0 deletions paket.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ lowest_matching: true
nuget BenchmarkDotNet 0.13.5
nuget Fantomas.Client >= 0.9
nuget FSharp.Compiler.Service >= 43.8.100
nuget Ionide.Analyzers 0.4.0
nuget FSharp.Analyzers.Build 0.2.0
nuget Ionide.ProjInfo >= 0.62.0
nuget Ionide.ProjInfo.FCS >= 0.62.0
nuget Ionide.ProjInfo.ProjectSystem >= 0.62.0
Expand Down Expand Up @@ -57,6 +59,8 @@ nuget OpenTelemetry.Exporter.OpenTelemetryProtocol >= 1.3.2 # 1.4 bumps to 7.0 v
nuget LinkDotNet.StringBuilder 1.18.0
nuget CommunityToolkit.HighPerformance
nuget System.Security.Cryptography.Pkcs 6.0.4
nuget System.Net.Http 4.3.4 # pinned for security reasons
nuget System.Text.RegularExpressions 4.3.1 # pinned for security reasons


group Build
Expand Down
467 changes: 459 additions & 8 deletions paket.lock

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions src/FsAutoComplete.Core/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -387,15 +387,15 @@ module Commands =
}

let formatSelection
(tryGetFileCheckerOptionsWithLines: _ -> Async<Result<IFSACSourceText, _>>)
(tryGetFileCheckerOptionsWithLines: _ -> Async<IFSACSourceText option>)
(formatSelectionAsync: _ -> System.Threading.Tasks.Task<FantomasResponse>)
(file: string<LocalPath>)
(rangeToFormat: FormatSelectionRange)
: Async<Result<FormatDocumentResponse, string>> =
asyncResult {
try
let filePath = (UMX.untag file)
let! text = tryGetFileCheckerOptionsWithLines file
let! text = tryGetFileCheckerOptionsWithLines file |> AsyncResult.ofOption (fun _ -> $"Could not get file checker options in file: {file}")
let currentCode = string text

let! fantomasResponse =
Expand Down Expand Up @@ -444,14 +444,14 @@ module Commands =
}

let formatDocument
(tryGetFileCheckerOptionsWithLines: _ -> Async<Result<IFSACSourceText, _>>)
(tryGetFileCheckerOptionsWithLines: _ -> Async<IFSACSourceText option>)
(formatDocumentAsync: _ -> System.Threading.Tasks.Task<FantomasResponse>)
(file: string<LocalPath>)
: Async<Result<FormatDocumentResponse, string>> =
asyncResult {
try
let filePath = (UMX.untag file)
let! text = tryGetFileCheckerOptionsWithLines file
let! text = tryGetFileCheckerOptionsWithLines file |> AsyncResult.ofOption (fun _ -> $"Could not get file checker options in file: {file}")
let currentCode = string text

let! fantomasResponse =
Expand Down Expand Up @@ -605,10 +605,10 @@ module Commands =
|> AsyncResult.foldResult id (fun _ -> [||])


let pipelineHints (tryGetFileSource: _ -> Async<Result<IFSACSourceText, _>>) (tyRes: ParseAndCheckResults) =
let pipelineHints (tryGetFileSource: _ -> Async<IFSACSourceText option>) (tyRes: ParseAndCheckResults) =
asyncResult {
// Debug.waitForDebuggerAttached "AdaptiveServer"
let! contents = tryGetFileSource tyRes.FileName
let! contents = tryGetFileSource tyRes.FileName |> AsyncResult.ofOption (fun _ -> $"Couldn't find file: {tyRes.FileName}")

let getSignatureAtPos pos =
option {
Expand Down Expand Up @@ -731,7 +731,7 @@ module Commands =
let symbolUseWorkspaceAux
(getDeclarationLocation: FSharpSymbolUse * IFSACSourceText -> Async<SymbolDeclarationLocation option>)
(findReferencesForSymbolInFile: (string<LocalPath> * FSharpProjectOptions * FSharpSymbol) -> Async<Range seq>)
(tryGetFileSource: string<LocalPath> -> Async<ResultOrString<IFSACSourceText>>)
(tryGetFileSource: string<LocalPath> -> Async<IFSACSourceText option>)
(tryGetProjectOptionsForFsproj: string<LocalPath> -> Async<FSharpProjectOptions option>)
(getAllProjectOptions: unit -> Async<FSharpProjectOptions seq>)
(includeDeclarations: bool)
Expand Down Expand Up @@ -817,9 +817,9 @@ module Commands =
let tryAdjustRanges (file: string<LocalPath>, ranges: Range[]) =
async {
match! tryGetFileSource file with
| Error _ when errorOnFailureToFixRange -> return Error $"Cannot get source of '{file}'"
| Error _ -> return Ok ranges
| Ok text ->
| None when errorOnFailureToFixRange -> return Error $"Cannot get source of '{file}'"
| None -> return Ok ranges
| Some text ->
return
tryAdjustRanges (text, ranges)
// Note: `Error` only possible when `errorOnFailureToFixRange`
Expand Down Expand Up @@ -930,7 +930,7 @@ module Commands =
let symbolUseWorkspace
(getDeclarationLocation: FSharpSymbolUse * IFSACSourceText -> Async<SymbolDeclarationLocation option>)
(findReferencesForSymbolInFile: (string<LocalPath> * FSharpProjectOptions * FSharpSymbol) -> Async<Range seq>)
(tryGetFileSource: string<LocalPath> -> Async<ResultOrString<IFSACSourceText>>)
(tryGetFileSource: string<LocalPath> -> Async<IFSACSourceText option>)
(tryGetProjectOptionsForFsproj: string<LocalPath> -> Async<FSharpProjectOptions option>)
(getAllProjectOptions: unit -> Async<FSharpProjectOptions seq>)
(includeDeclarations: bool)
Expand Down
4 changes: 3 additions & 1 deletion src/FsAutoComplete.Core/SignatureFormatter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -552,10 +552,12 @@ module SignatureFormatter =

let getAPCaseSignature displayContext (apc: FSharpActivePatternCase) =
let findVal =
let apcSearchString = $"|{apc.DisplayName}|"

apc.Group.DeclaringEntity
|> Option.bind (fun ent ->
ent.MembersFunctionsAndValues
|> Seq.tryFind (fun func -> func.DisplayName.Contains apc.DisplayName)
|> Seq.tryFind (fun func -> func.DisplayName.Contains(apcSearchString, StringComparison.OrdinalIgnoreCase))
|> Option.map (getFuncSignature displayContext))
|> Option.bind (fun n ->
try
Expand Down
22 changes: 22 additions & 0 deletions src/FsAutoComplete.Core/TipFormatter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,26 @@ let rec private readXmlDoc (reader: XmlReader) (indentationSize: int) (acc: Map<
let private xmlDocCache =
Collections.Concurrent.ConcurrentDictionary<string, Map<string, XmlDocMember>>()

let private findCultures v =
let rec loop state (v: System.Globalization.CultureInfo) =
let state' = v.Name :: state

if v.Parent = System.Globalization.CultureInfo.InvariantCulture then
"" :: state' |> List.rev
else
loop state' v.Parent

loop [] v

let private findLocalizedXmlFile (xmlFile: string) =
let xmlName = Path.GetFileName xmlFile
let path = Path.GetDirectoryName xmlFile

findCultures System.Globalization.CultureInfo.CurrentUICulture
|> List.map (fun culture -> Path.Combine(path, culture, xmlName))
|> List.tryFind (fun i -> File.Exists i)
|> Option.defaultValue xmlFile

let private getXmlDoc dllFile =
let xmlFile = Path.ChangeExtension(dllFile, ".xml")
//Workaround for netstandard.dll
Expand All @@ -908,6 +928,8 @@ let private getXmlDoc dllFile =
else
xmlFile

let xmlFile = findLocalizedXmlFile xmlFile

if xmlDocCache.ContainsKey xmlFile then
Some xmlDocCache.[xmlFile]
else
Expand Down
4 changes: 3 additions & 1 deletion src/FsAutoComplete.Core/paket.references
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ Ionide.KeepAChangelog.Tasks
Microsoft.Extensions.Caching.Memory
Microsoft.CodeAnalysis
LinkDotNet.StringBuilder
CommunityToolkit.HighPerformance
CommunityToolkit.HighPerformance
Ionide.Analyzers
FSharp.Analyzers.Build
2 changes: 2 additions & 0 deletions src/FsAutoComplete.Logging/paket.references
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ FSharp.Core

Microsoft.NETFramework.ReferenceAssemblies
Ionide.KeepAChangelog.Tasks
Ionide.Analyzers
FSharp.Analyzers.Build
5 changes: 4 additions & 1 deletion src/FsAutoComplete/CodeFixes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module Types =
type IsEnabled = unit -> bool

type GetRangeText = string<LocalPath> -> LspTypes.Range -> Async<ResultOrString<string>>
type GetFileLines = string<LocalPath> -> Async<ResultOrString<IFSACSourceText>>
type GetFileLines = string<LocalPath> -> Async<IFSACSourceText option>
type GetLineText = IFSACSourceText -> LspTypes.Range -> Async<Result<string, string>>

type GetParseResultsForFile =
Expand Down Expand Up @@ -326,6 +326,9 @@ module Run =
let ifDiagnosticByMessage (checkMessage: string) handler : CodeFix =
runDiagnostics (fun d -> d.Message.Contains checkMessage) handler

let ifDiagnosticByCheckMessage (checkMessageFunc: (string -> bool) list) handler : CodeFix =
runDiagnostics (fun d -> checkMessageFunc |> List.exists (fun f -> f d.Message)) handler

let ifDiagnosticByType (diagnosticType: string) handler : CodeFix =
runDiagnostics
(fun d ->
Expand Down
7 changes: 6 additions & 1 deletion src/FsAutoComplete/CodeFixes.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module LspTypes = Ionide.LanguageServerProtocol.Types
module Types =
type IsEnabled = unit -> bool
type GetRangeText = string<LocalPath> -> LspTypes.Range -> Async<ResultOrString<string>>
type GetFileLines = string<LocalPath> -> Async<ResultOrString<IFSACSourceText>>
type GetFileLines = string<LocalPath> -> Async<IFSACSourceText option>
type GetLineText = IFSACSourceText -> LspTypes.Range -> Async<Result<string, string>>

type GetParseResultsForFile =
Expand Down Expand Up @@ -162,6 +162,11 @@ module Run =
handler: (Diagnostic -> CodeActionParams -> Async<Result<Fix list, string>>) ->
(CodeActionParams -> Async<Result<Fix list, string>>)

val ifDiagnosticByCheckMessage:
checkMessageFunc: (string -> bool) list ->
handler: (Diagnostic -> CodeActionParams -> Async<Result<Fix list, string>>) ->
(CodeActionParams -> Async<Result<Fix list, string>>)

val ifDiagnosticByType:
diagnosticType: string ->
handler: (Diagnostic -> CodeActionParams -> Async<Result<Fix list, string>>) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let fix (getFileLines: GetFileLines) =
asyncResult {
let fileName = codeActionParams.TextDocument.GetFilePath() |> Utils.normalizePath

let! lines = getFileLines fileName
let! lines = getFileLines fileName |> AsyncResult.ofOption (fun _ -> $"Could not get file lines in file: {fileName}")

let! walkPos = dec lines diagnostic.Range.Start |> Result.ofOption (fun _ -> "No walk pos")

Expand Down
3 changes: 2 additions & 1 deletion src/FsAutoComplete/CodeFixes/AddMissingFunKeyword.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ let fix (getFileLines: GetFileLines) (getLineText: GetLineText) : CodeFix =
asyncResult {
let fileName = codeActionParams.TextDocument.GetFilePath() |> Utils.normalizePath

let! lines = getFileLines fileName
let! lines = getFileLines fileName |> AsyncResult.ofOption (fun _ -> $"Could not get file lines in file: {fileName}")

let! errorText = getLineText lines diagnostic.Range
do! Result.guard (fun _ -> errorText = "->") "Expected error source code text not matched"

Expand Down
2 changes: 1 addition & 1 deletion src/FsAutoComplete/CodeFixes/AddMissingRecKeyword.fs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let fix (getFileLines: GetFileLines) (getLineText: GetLineText) : CodeFix =
asyncResult {
let fileName = codeActionParams.TextDocument.GetFilePath() |> Utils.normalizePath

let! lines = getFileLines fileName
let! lines = getFileLines fileName |> AsyncResult.ofOption (fun _ -> $"Could not get file lines in file: {fileName}")
let endOfError = diagnostic.Range.End
// this next bit is a bit 'extra': we technically could just slap an ' rec' at the end of the error diagnostic,
// but instead we're fancy and:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let fix (getFileLines: GetFileLines) : CodeFix =
asyncResult {
let fileName = codeActionParams.TextDocument.GetFilePath() |> Utils.normalizePath

let! lines = getFileLines fileName
let! lines = getFileLines fileName |> AsyncResult.ofOption (fun _ -> $"Could not get file lines in file: {fileName}")

let! walkPos = inc lines diagnostic.Range.End |> Result.ofOption (fun _ -> "No walk pos")

Expand Down
3 changes: 2 additions & 1 deletion src/FsAutoComplete/CodeFixes/GenerateUnionCases.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ let fix
asyncResult {
let fileName = codeActionParams.TextDocument.GetFilePath() |> Utils.normalizePath

let! lines = getFileLines fileName
let! lines = getFileLines fileName |> AsyncResult.ofOption (fun _ -> $"Could not get file lines in file: {fileName}")

// try to find the first case already written
let fcsRange = protocolRangeToRange (FSharp.UMX.UMX.untag fileName) diagnostic.Range

Expand Down
2 changes: 1 addition & 1 deletion src/FsAutoComplete/CodeFixes/RemoveUnusedOpens.fs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let fix (getFileLines: GetFileLines) : CodeFix =
asyncResult {
let fileName = codeActionParams.TextDocument.GetFilePath() |> Utils.normalizePath

let! lines = getFileLines fileName
let! lines = getFileLines fileName |> AsyncResult.ofOption (fun _ -> $"Could not get file lines in file: {fileName}")

let lineToRemove = d.Range.Start.Line
let range = lines |> rangeToDeleteFullLine lineToRemove
Expand Down
21 changes: 19 additions & 2 deletions src/FsAutoComplete/CodeFixes/ReplaceWithSuggestion.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,27 @@ open FSharp.Compiler.Syntax

let title suggestion = $"Replace with '%s{suggestion}'"

let undefinedName =
[ "Maybe you want one of the following:"
"Možná budete potřebovat něco z tohoto:"
"Vielleicht möchten Sie eine der folgenden Bezeichnungen verwenden:"
"Puede elegir una de las opciones siguientes:"
"Peut-être souhaitez-vous l'une des options suivantes :"
"Si può specificare uno dei nomi seguenti:"
"次のいずれかの可能性はありませんか:"
"다음 중 하나가 필요할 수 있습니다:"
"Możliwe, że chcesz wykonać jedną z następujących czynności:"
"Talvez você queira um dos seguintes:"
"Возможно, требуется одно из следующих:"
"Aşağıdakilerden birini arıyor olabilirsiniz:"
"你可能需要以下之一:"
"您可能需要下列其中一項:" ]
|> List.map (fun i -> fun (j: string) -> j.Contains(i, System.StringComparison.Ordinal))

/// a codefix that replaces the use of an unknown identifier with a suggested identifier
let fix =
Run.ifDiagnosticByMessage "Maybe you want one of the following:" (fun diagnostic codeActionParams ->
diagnostic.Message.Split('\n').[1..]
Run.ifDiagnosticByCheckMessage undefinedName (fun diagnostic codeActionParams ->
diagnostic.Message.Split('\n', '\u001b').[1..]
|> Array.map (fun suggestion ->
let suggestion = suggestion.Trim() |> PrettyNaming.NormalizeIdentifierBackticks

Expand Down
Loading
Loading