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

Using AsyncAdaptive #1088

Merged
merged 10 commits into from
Apr 12, 2023
Merged
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
4 changes: 2 additions & 2 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
]
},
"paket": {
"version": "7.2.0-alpha001",
"version": "7.2.1",
"commands": [
"paket"
]
Expand All @@ -33,4 +33,4 @@
]
}
}
}
}
36 changes: 21 additions & 15 deletions paket.dependencies
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
version 7.2.0-alpha001
version 7.2.1

framework: netstandard2.0, net6.0, net7.0
framework: netstandard2.0, netstandard2.1, net6.0, net7.0

source https://api.nuget.org/v3/index.json
# this is the FCS nightly feed, re-enable at your own risk!
#source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json
#source: ./libs
storage: none
strategy: min
lowest_matching: true


nuget Fantomas.Client
nuget FSharp.Compiler.Service
nuget Ionide.ProjInfo
nuget Ionide.ProjInfo.FCS
nuget Ionide.ProjInfo.ProjectSystem
nuget Ionide.ProjInfo.Sln
nuget Microsoft.Build copy_local:false
nuget Microsoft.Build.Framework copy_local:false
nuget Microsoft.Build.Utilities.Core copy_local:false
nuget Microsoft.Build.Tasks.Core copy_local: false
nuget Fantomas.Client >= 0.9
nuget FSharp.Compiler.Service >= 43.7.200
nuget Ionide.ProjInfo >= 0.61.3
nuget Ionide.ProjInfo.FCS >= 0.61.3
nuget Ionide.ProjInfo.ProjectSystem >= 0.61.3
nuget Ionide.ProjInfo.Sln >= 0.61.3
nuget Microsoft.Build >= 17.2 copy_local:false
nuget Microsoft.Build.Framework >= 17.4 copy_local:false
nuget Microsoft.Build.Utilities.Core >= 17.4 copy_local:false
nuget Microsoft.Build.Tasks.Core >= 17.4 copy_local: false
nuget Nuget.Frameworks copy_local: false
nuget FSharp.Analyzers.SDK
nuget ICSharpCode.Decompiler
Expand All @@ -34,7 +36,8 @@ nuget Serilog.Sinks.Async
nuget Destructurama.FSharp
nuget FSharp.UMX
nuget FSharp.Formatting
nuget FsToolkit.ErrorHandling
nuget FsToolkit.ErrorHandling.TaskResult framework: netstandard2.1 ,net6.0, net7.0
nuget IcedTasks
nuget FSharpx.Async
nuget CliWrap
nuget System.CommandLine prerelease
Expand All @@ -49,9 +52,12 @@ nuget Expecto.Diff
nuget YoloDev.Expecto.TestSdk
nuget AltCover
nuget GitHubActionsTestLogger
nuget Ionide.LanguageServerProtocol
nuget Ionide.LanguageServerProtocol >= 0.4.12
nuget Microsoft.Extensions.Caching.Memory
nuget OpenTelemetry.Exporter.OpenTelemetryProtocol
nuget OpenTelemetry.Exporter.OpenTelemetryProtocol >= 1.3.2




group Build
source https://api.nuget.org/v3/index.json
Expand Down
259 changes: 133 additions & 126 deletions paket.lock

Large diffs are not rendered by default.

109 changes: 60 additions & 49 deletions src/FsAutoComplete.Core/AbstractClassStubGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ open FSharp.Compiler.Syntax
open FSharp.Compiler.Symbols
open FSharp.Compiler.Tokenization
open FsAutoComplete.Logging
open FsToolkit.ErrorHandling


type AbstractClassData =
Expand Down Expand Up @@ -122,26 +123,29 @@ let inferStartColumn
(abstractClassData: AbstractClassData)
(indentSize: int)
=
match getMemberNameAndRanges abstractClassData with
| (_, range) :: _ -> getLineIdent (lines.GetLineString(range.StartLine - 1))
| [] ->
match abstractClassData with
| AbstractClassData.ExplicitImpl _ ->
// 'interface ISomething with' is often in a new line, we use the indentation of that line
getLineIdent lineStr + indentSize
| AbstractClassData.ObjExpr(_, _, newExprRange) ->
match codeGenServer.TokenizeLine(doc.FullName, pos.Line) with
| Some tokens ->
tokens
|> List.tryPick (fun (t: FSharpTokenInfo) ->
if t.CharClass = FSharpTokenCharKind.Keyword && t.TokenName = "NEW" then
// We round to nearest so the generated code will align on the indentation guides
findGreaterMultiple (t.LeftColumn + indentSize) indentSize |> Some
else
None)
// There is no reference point, we indent the content at the start column of the interface
|> Option.defaultValue newExprRange.StartColumn
| None -> newExprRange.StartColumn
async {
match getMemberNameAndRanges abstractClassData with
| (_, range) :: _ -> return getLineIdent (lines.GetLineString(range.StartLine - 1))
| [] ->
match abstractClassData with
| AbstractClassData.ExplicitImpl _ ->
// 'interface ISomething with' is often in a new line, we use the indentation of that line
return getLineIdent lineStr + indentSize
| AbstractClassData.ObjExpr(_, _, newExprRange) ->
match! codeGenServer.TokenizeLine(doc.FullName, pos.Line) with
| Some tokens ->
return
tokens
|> List.tryPick (fun (t: FSharpTokenInfo) ->
if t.CharClass = FSharpTokenCharKind.Keyword && t.TokenName = "NEW" then
// We round to nearest so the generated code will align on the indentation guides
findGreaterMultiple (t.LeftColumn + indentSize) indentSize |> Some
else
None)
// There is no reference point, we indent the content at the start column of the interface
|> Option.defaultValue newExprRange.StartColumn
| None -> return newExprRange.StartColumn
}

/// Try to write any missing members of the given abstract type at the given location.
/// If the destination type isn't an abstract class, or if there are no missing members to implement,
Expand All @@ -154,7 +158,7 @@ let writeAbstractClassStub
(lineStr: string)
(abstractClassData: AbstractClassData)
=
asyncMaybe {
asyncOption {
let pos =
Position.mkPos
abstractClassData.AbstractTypeIdentRange.Start.Line
Expand All @@ -164,7 +168,7 @@ let writeAbstractClassStub
let! usage = usages

let! (displayContext, entity) =
asyncMaybe {
asyncOption {
// need the enclosing entity because we're always looking at a ctor, which isn't an Entity, but a MemberOrFunctionOrValue
match usage.Symbol with
| :? FSharpMemberOrFunctionOrValue as v ->
Expand All @@ -177,51 +181,58 @@ let writeAbstractClassStub
}

let getMemberByLocation (name, range: Range) =
asyncMaybe {
asyncOption {
let pos = Position.fromZ (range.StartLine - 1) (range.StartColumn + 1)
return! checkResultForFile.GetCheckResults.GetSymbolUseAtLocation(pos.Line, pos.Column, lineStr, [])
}

let insertInfo =
match codeGenServer.TokenizeLine(doc.FullName, pos.Line) with
| Some tokens ->
match abstractClassData with
| AbstractClassData.ObjExpr _ ->
findLastPositionOfWithKeyword tokens entity pos (getAbstractClassIdentifier abstractClassData)
| AbstractClassData.ExplicitImpl(_, _, safeInsertPosition) -> Some(false, safeInsertPosition)
| None -> None
asyncOption {
let! tokens = codeGenServer.TokenizeLine(doc.FullName, pos.Line)

return
match abstractClassData with
| AbstractClassData.ObjExpr _ ->
findLastPositionOfWithKeyword tokens entity pos (getAbstractClassIdentifier abstractClassData)
| AbstractClassData.ExplicitImpl(_, _, safeInsertPosition) -> Some(false, safeInsertPosition)

}

let desiredMemberNamesWithRanges = getMemberNameAndRanges abstractClassData

let! implementedSignatures =
getImplementedMemberSignatures getMemberByLocation displayContext desiredMemberNamesWithRanges
|> Async.map Some

let generatedString =
let formattedString =
formatMembersAt
(inferStartColumn codeGenServer pos doc lines lineStr abstractClassData 4) // 4 here correspond to the indent size
4 // Should we make it a setting from the IDE ?
abstractClassData.TypeParameters
"$objectIdent"
"$methodBody"
displayContext
implementedSignatures
entity
getAbstractNonVirtualMembers
true // Always generate the verbose version of the code

// If we are in a object expression, we remove the last new line, so the `}` stay on the same line
match abstractClassData with
| AbstractClassData.ExplicitImpl _ -> formattedString
| AbstractClassData.ObjExpr _ -> formattedString.TrimEnd('\n')
let! generatedString =
async {
let! start = (inferStartColumn codeGenServer pos doc lines lineStr abstractClassData 4) // 4 here correspond to the indent size

let formattedString =
formatMembersAt
start
4 // Should we make it a setting from the IDE ?
abstractClassData.TypeParameters
"$objectIdent"
"$methodBody"
displayContext
implementedSignatures
entity
getAbstractNonVirtualMembers
true // Always generate the verbose version of the code

// If we are in a object expression, we remove the last new line, so the `}` stay on the same line
match abstractClassData with
| AbstractClassData.ExplicitImpl _ -> return formattedString
| AbstractClassData.ObjExpr _ -> return formattedString.TrimEnd('\n')
}

// If generatedString is empty it means nothing is missing to the abstract class
// So we return None, in order to not show a "Falsy Hint"
if System.String.IsNullOrEmpty generatedString then
return! None
else
match insertInfo with
match! insertInfo with
| Some(shouldAppendWith, insertPosition) ->
if shouldAppendWith then
return! Some(insertPosition, " with" + generatedString)
Expand Down
Loading