Skip to content

Static parameters of type provider completion #18427

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
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
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/9.0.300.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* Symbols: Add FSharpAssembly.IsFSharp ([PR #18290](https://github.com/dotnet/fsharp/pull/18290))
* Type parameter constraint `null` in generic code will now automatically imply `not struct` ([Issue #18320](https://github.com/dotnet/fsharp/issues/18320), [PR #18323](https://github.com/dotnet/fsharp/pull/18323))
* Add a switch to determine whether to generate a default implementation body for overridden method when completing. [PR #18341](https://github.com/dotnet/fsharp/pull/18341)
* Static parameters of type provider completion. ([PR #18427](https://github.com/dotnet/fsharp/pull/18427))


### Changed
Expand Down
47 changes: 47 additions & 0 deletions src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,53 @@ type internal TypeCheckInfo
getDeclaredItemsNotInRangeOpWithAllSymbols ()
|> Option.bind (FilterRelevantItemsBy getItem2 None IsTypeCandidate)

| Some(CompletionContext.TypeProviderStaticArgumentList(_endPos, _fields)) ->
#if NO_TYPEPROVIDERS
getDeclaredItemsNotInRangeOpWithAllSymbols ()
|> Option.bind (FilterRelevantItemsBy getItem2 None IsTypeCandidate)
#else
let cnrs = GetCapturedNameResolutions _endPos ResolveOverloads.No

if cnrs.Count = 0 then
getDeclaredItemsNotInRangeOpWithAllSymbols ()
|> Option.bind (FilterRelevantItemsBy getItem2 None IsTypeCandidate)
else
let cnr = cnrs[cnrs.Count - 1]
let m = cnr.Range

match cnr with
// If the type is a type provider, return the static parameter names
| CNR((Item.Types(_, containerTy :: _) & ItemIsProvidedTypeWithStaticArguments m g staticParameters), _, denv, _, _, _) ->
let staticParameters =
staticParameters
|> Array.choose (fun sp ->
let name = sp.PUntaint((fun sp -> sp.Name), m)

if _fields.Contains name then
None
else
let ty =
Import.ImportProvidedType amap m (sp.PApply((fun sp -> sp.ParameterType), m))

Item.OtherName(
Some(Ident(name, m)),
ty,
None,
Some(containerTy |> tcrefOfAppTy g |> ArgumentContainer.Type),
m
)
|> ItemWithNoInst
|> Some)
|> Array.toList

Some(toCompletionItems (staticParameters, denv, m))

// If the type is not type provider, return the types
| _ ->
getDeclaredItemsNotInRangeOpWithAllSymbols ()
|> Option.bind (FilterRelevantItemsBy getItem2 None IsTypeCandidate)
#endif

| Some(CompletionContext.Pattern patternContext) ->
match patternContext with
| PatternContext.UnionCaseFieldIdentifier(referencedFields, caseIdRange) ->
Expand Down
9 changes: 0 additions & 9 deletions src/Compiler/Service/ServiceParamInfoLocations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,6 @@ type ParameterLocations
[<AutoOpen>]
module internal ParameterLocationsImpl =

let isStaticArg (StripParenTypes synType) =
match synType with
| SynType.StaticConstant _
| SynType.StaticConstantNull _
| SynType.StaticConstantExpr _
| SynType.StaticConstantNamed _ -> true
| SynType.LongIdent _ -> true // NOTE: this is not a static constant, but it is a prefix of incomplete code, e.g. "TP<42, Arg3" is a prefix of "TP<42, Arg3=6>" and Arg3 shows up as a LongId
| _ -> false

/// Dig out an identifier from an expression that used in an application
let rec digOutIdentFromFuncExpr synExpr =
// we found it, dig out ident
Expand Down
29 changes: 27 additions & 2 deletions src/Compiler/Service/ServiceParsedInputOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ type CompletionContext =
isStatic: bool *
spacesBeforeEnclosingDefinition: int

| TypeProviderStaticArgumentList of typeNameEndPos: pos * assignedParams: HashSet<string>

type ShortIdent = string

type ShortIdents = ShortIdent[]
Expand Down Expand Up @@ -1454,6 +1456,19 @@ module ParsedInput =

| SynExpr.Record(None, None, [], _) -> Some(CompletionContext.RecordField RecordContext.Empty)

// TypeProvider<$>.
| SynExpr.TypeApp(expr, _, args, _, _, typeArgsRange, _) when
rangeContainsPos typeArgsRange pos && args |> List.forall isStaticArg
->
let argNames =
args
|> List.choose (function
| SynType.StaticConstantNamed(SynType.LongIdent lid, _, _) -> Some lid.LongIdent.Head.idText
| _ -> None)
|> HashSet

Some(CompletionContext.TypeProviderStaticArgumentList(expr.Range.End, argNames))

// Unchecked.defaultof<str$>
| SynExpr.TypeApp(typeArgsRange = range) when rangeContainsPos range pos -> Some CompletionContext.Type

Expand Down Expand Up @@ -1815,9 +1830,19 @@ module ParsedInput =
// The value expression should still get completions
None)

member _.VisitTypeAbbrev(_, _, range) =
member _.VisitTypeAbbrev(_, ty, range) =
if rangeContainsPos range pos then
Some CompletionContext.TypeAbbreviationOrSingleCaseUnion
match ty with
| SynType.App(SynType.LongIdent lid, _, args, _, _, false, _) when args |> List.forall isStaticArg ->
let argNames =
args
|> List.choose (function
| SynType.StaticConstantNamed(SynType.LongIdent lid, _, _) -> Some lid.LongIdent.Head.idText
| _ -> None)
|> HashSet

Some(CompletionContext.TypeProviderStaticArgumentList(lid.Range.End, argNames))
| _ -> Some CompletionContext.TypeAbbreviationOrSingleCaseUnion
else
None

Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/Service/ServiceParsedInputOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ type public CompletionContext =
isStatic: bool *
spacesBeforeEnclosingDefinition: int

/// Completing static named parameters of a type provider. `NonProviderType<$>` will also match this.
| TypeProviderStaticArgumentList of typeNameEndPos: pos * assignedParams: HashSet<string>

type public ModuleKind =
{ IsAutoOpen: bool
HasModuleSuffix: bool }
Expand Down
9 changes: 9 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,15 @@ let rec stripParenTypes synType =

let (|StripParenTypes|) synType = stripParenTypes synType

let isStaticArg (StripParenTypes synType) =
match synType with
| SynType.StaticConstant _
| SynType.StaticConstantNull _
| SynType.StaticConstantExpr _
| SynType.StaticConstantNamed _ -> true
| SynType.LongIdent _ -> true // NOTE: this is not a static constant, but it is a prefix of incomplete code, e.g. "TP<42, Arg3" is a prefix of "TP<42, Arg3=6>" and Arg3 shows up as a LongId
| _ -> false

/// Operations related to the syntactic analysis of arguments of value, function and member definitions and signatures.
module SynInfo =

Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTreeOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ val stripParenTypes: synType: SynType -> SynType

val (|StripParenTypes|): synType: SynType -> SynType

val isStaticArg: SynType -> bool

/// Operations related to the syntactic analysis of arguments of value, function and member definitions and signatures.
module SynInfo =
/// The argument information for an argument without a name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3072,7 +3072,12 @@ FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RangeOperator
FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RecordField
FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 Type
FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 TypeAbbreviationOrSingleCaseUnion
FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 TypeProviderStaticArgumentList
FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 UnionCaseFieldsDeclaration
FSharp.Compiler.EditorServices.CompletionContext+TypeProviderStaticArgumentList: FSharp.Compiler.Text.Position get_typeNameEndPos()
FSharp.Compiler.EditorServices.CompletionContext+TypeProviderStaticArgumentList: FSharp.Compiler.Text.Position typeNameEndPos
FSharp.Compiler.EditorServices.CompletionContext+TypeProviderStaticArgumentList: System.Collections.Generic.HashSet`1[System.String] assignedParams
FSharp.Compiler.EditorServices.CompletionContext+TypeProviderStaticArgumentList: System.Collections.Generic.HashSet`1[System.String] get_assignedParams()
FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(FSharp.Compiler.EditorServices.CompletionContext)
FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(FSharp.Compiler.EditorServices.CompletionContext, System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(System.Object)
Expand All @@ -3088,6 +3093,7 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRangeOperator
FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRecordField
FSharp.Compiler.EditorServices.CompletionContext: Boolean IsType
FSharp.Compiler.EditorServices.CompletionContext: Boolean IsTypeAbbreviationOrSingleCaseUnion
FSharp.Compiler.EditorServices.CompletionContext: Boolean IsTypeProviderStaticArgumentList
FSharp.Compiler.EditorServices.CompletionContext: Boolean IsUnionCaseFieldsDeclaration
FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsAttributeApplication()
FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsInherit()
Expand All @@ -3100,6 +3106,7 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRangeOperator()
FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRecordField()
FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsType()
FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsTypeAbbreviationOrSingleCaseUnion()
FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsTypeProviderStaticArgumentList()
FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsUnionCaseFieldsDeclaration()
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext AttributeApplication
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext Invalid
Expand All @@ -3109,6 +3116,7 @@ FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewParameterList(FSharp.Compiler.Text.Position, System.Collections.Generic.HashSet`1[System.String])
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewPattern(FSharp.Compiler.EditorServices.PatternContext)
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewRecordField(FSharp.Compiler.EditorServices.RecordContext)
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewTypeProviderStaticArgumentList(FSharp.Compiler.Text.Position, System.Collections.Generic.HashSet`1[System.String])
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext RangeOperator
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext Type
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext TypeAbbreviationOrSingleCaseUnion
Expand All @@ -3126,6 +3134,7 @@ FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+Pattern
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+RecordField
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+Tags
FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+TypeProviderStaticArgumentList
FSharp.Compiler.EditorServices.CompletionContext: Int32 GetHashCode()
FSharp.Compiler.EditorServices.CompletionContext: Int32 GetHashCode(System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.CompletionContext: Int32 Tag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+MagicAssemblyResolution::ResolveAssemblyCore([FSharp.Compiler.Service]Internal.Utilities.Library.CompilationThreadToken, [FSharp.Compiler.Service]FSharp.Compiler.Text.Range, [FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, [FSharp.Compiler.Service]FSharp.Compiler.CompilerImports+TcImports, [FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiDynamicCompiler, [FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiConsoleOutput, string)][offset 0x00000015][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+clo@3502-805::Invoke([S.P.CoreLib]System.Tuple`3<char[],int32,int32>)][offset 0x000001E5][found Char] Unexpected type on the stack.
[IL]: Error [UnmanagedPointer]: : FSharp.Compiler.Interactive.Shell+Utilities+pointerToNativeInt@110::Invoke(object)][offset 0x00000007] Unmanaged pointers are not a verifiable type.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharpCheckerResults+dataTipOfReferences@2225::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000084][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharpCheckerResults+dataTipOfReferences@2272::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000084][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-509::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000032][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-509::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000003B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-509::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000082][found Char] Unexpected type on the stack.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+clo@3502-805::Invoke([S.P.CoreLib]System.Tuple`3<char[],int32,int32>)][offset 0x000001E5][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+FsiInteractionProcessor::CompletionsForPartialLID([FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiDynamicCompilerState, string)][offset 0x0000001B][found Char] Unexpected type on the stack.
[IL]: Error [UnmanagedPointer]: : FSharp.Compiler.Interactive.Shell+Utilities+pointerToNativeInt@110::Invoke(object)][offset 0x00000007] Unmanaged pointers are not a verifiable type.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharpCheckerResults+dataTipOfReferences@2225::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000084][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharpCheckerResults+dataTipOfReferences@2272::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000084][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.EditorServices.AssemblyContent+traverseMemberFunctionAndValues@176::Invoke([FSharp.Compiler.Service]FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue)][offset 0x00000059][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.EditorServices.AssemblyContent+traverseEntity@218::GenerateNext([S.P.CoreLib]System.Collections.Generic.IEnumerable`1<FSharp.Compiler.EditorServices.AssemblySymbol>&)][offset 0x000000DA][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.EditorServices.ParsedInput+visitor@1424-6::VisitExpr([FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<FSharp.Compiler.Syntax.SyntaxNode>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1<FSharp.Compiler.EditorServices.CompletionContext>>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1<FSharp.Compiler.EditorServices.CompletionContext>>, [FSharp.Compiler.Service]FSharp.Compiler.Syntax.SynExpr)][offset 0x00000605][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.EditorServices.ParsedInput+visitor@1426-6::VisitExpr([FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<FSharp.Compiler.Syntax.SyntaxNode>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1<FSharp.Compiler.EditorServices.CompletionContext>>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1<FSharp.Compiler.EditorServices.CompletionContext>>, [FSharp.Compiler.Service]FSharp.Compiler.Syntax.SynExpr)][offset 0x00000649][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-509::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000032][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-509::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000003B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-509::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000082][found Char] Unexpected type on the stack.
Expand Down
Loading
Loading