From e6734db1e47293d3bd450e2462f8fac76eac58f5 Mon Sep 17 00:00:00 2001 From: kerams Date: Sat, 6 Nov 2021 13:30:46 +0100 Subject: [PATCH 1/8] Improve record, union, enum completions --- src/fsharp/service/FSharpCheckerResults.fs | 9 ++++++- src/fsharp/service/ServiceParsedInputOps.fs | 27 ++++++++++++++++++++ src/fsharp/service/ServiceParsedInputOps.fsi | 4 +++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 8c6945d229b..8afaf57b856 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -974,6 +974,9 @@ type internal TypeCheckInfo Some(GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, [typeName])) |> Option.map toCompletionItems + // No completion at '...: string' + | Some(CompletionContext.RecordField(RecordContext.Declaration true)) -> None + // Completion at ' SomeMethod( ... ) ' with named arguments | Some(CompletionContext.ParameterList (endPos, fields)) -> let results = GetNamedParametersAndSettableFields endPos @@ -1022,7 +1025,11 @@ type internal TypeCheckInfo | _ -> false), denv, m) // Completion at '(x: ...)" - | Some CompletionContext.PatternType -> + | Some CompletionContext.PatternType + // Completion at '| Case1 of ...' + | Some CompletionContext.UnionCaseFieldsDeclaration + // Completion at 'Field1: ...' + | Some(CompletionContext.RecordField(RecordContext.Declaration false)) -> GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors, resolveOverloads, false, getAllSymbols) |> Option.map (fun (items, denv, m) -> items diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index 93c6fa25c88..06136b7f7ba 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -44,6 +44,7 @@ type RecordContext = | CopyOnUpdate of range: range * path: CompletionPath | Constructor of typeName: string | New of path: CompletionPath + | Declaration of isInIdentifier: bool [] type CompletionContext = @@ -69,6 +70,9 @@ type CompletionContext = /// Completing pattern type (e.g. foo (x: |)) | PatternType + /// Completing union case fields declaration (e.g. 'A of stri|' but not 'B of tex|: string') + | UnionCaseFieldsDeclaration + type ShortIdent = string type ShortIdents = ShortIdent[] @@ -1077,6 +1081,29 @@ module ParsedInput = | SynType.LongIdent _ when rangeContainsPos ty.Range pos -> Some CompletionContext.PatternType | _ -> defaultTraverse ty + + member _.VisitRecordDefn(_path, fields, _range) = + fields |> List.tryPick (fun (SynField (idOpt = idOpt; range = fieldRange)) -> + match idOpt with + | Some id when rangeContainsPos id.idRange pos -> Some(CompletionContext.RecordField(RecordContext.Declaration true)) + | _ when rangeContainsPos fieldRange pos -> Some(CompletionContext.RecordField(RecordContext.Declaration false)) + | _ -> None) + + member _.VisitUnionDefn(_path, cases, _range) = + cases |> List.tryPick (fun (SynUnionCase (ident = id; caseType = caseType)) -> + if rangeContainsPos id.idRange pos then + Some CompletionContext.Invalid + else + match caseType with + | SynUnionCaseKind.Fields fieldCases -> + fieldCases |> List.tryPick (fun (SynField (idOpt = fieldIdOpt; range = fieldRange)) -> + match fieldIdOpt with + | Some id when rangeContainsPos id.idRange pos -> Some CompletionContext.Invalid + | _ -> if rangeContainsPos fieldRange pos then Some CompletionContext.UnionCaseFieldsDeclaration else None) + | _ -> None) + + member _.VisitEnumDefn(_path, _, range) = + if rangeContainsPos range pos then Some CompletionContext.Invalid else None } SyntaxTraversal.Traverse(pos, parsedInput, walker) diff --git a/src/fsharp/service/ServiceParsedInputOps.fsi b/src/fsharp/service/ServiceParsedInputOps.fsi index d0c36e03cc9..21c9e06a726 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fsi +++ b/src/fsharp/service/ServiceParsedInputOps.fsi @@ -19,6 +19,7 @@ type public RecordContext = | CopyOnUpdate of range: range * path: CompletionPath | Constructor of typeName: string | New of path: CompletionPath + | Declaration of isInIdentifier: bool [] type public CompletionContext = @@ -44,6 +45,9 @@ type public CompletionContext = /// Completing pattern type (e.g. foo (x: |)) | PatternType + /// Completing union case fields declaration (e.g. 'A of stri|' but not 'B of tex|: string') + | UnionCaseFieldsDeclaration + type public ModuleKind = { IsAutoOpen: bool HasModuleSuffix: bool } From d76ff927fe75985d0235bae7bea278f4d6952bc1 Mon Sep 17 00:00:00 2001 From: kerams Date: Fri, 12 Nov 2021 18:13:41 +0100 Subject: [PATCH 2/8] Tests --- .../UnitTests/CompletionProviderTests.fs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/vsintegration/tests/UnitTests/CompletionProviderTests.fs b/vsintegration/tests/UnitTests/CompletionProviderTests.fs index 65f16f53ff8..b1cfc635610 100644 --- a/vsintegration/tests/UnitTests/CompletionProviderTests.fs +++ b/vsintegration/tests/UnitTests/CompletionProviderTests.fs @@ -736,6 +736,60 @@ let x = A.``B C`` + D.``E F`` """ VerifyCompletionListSpan(fileContents, "D.``E F``", "``E F``") +[] +let ``No completion on record field identifier at declaration site``() = + let fileContents = """ +type A = { le: string } +""" + VerifyNoCompletionList(fileContents, "le") + +[] +let ``Completion list on record field type at declaration site contains modules and types but not keywords or functions``() = + let fileContents = """ +type A = { Field: l } +""" + VerifyCompletionList(fileContents, "Field: l", ["LanguagePrimitives"; "List"], ["let"; "log"]) + +[] +let ``No completion on union case identifier at declaration site``() = + let fileContents = """ +type A = + | C of string +""" + VerifyNoCompletionList(fileContents, "| C") + +[] +let ``No completion on union case field identifier at declaration site``() = + let fileContents = """ +type A = + | Case of blah: int * str: int +""" + VerifyNoCompletionList(fileContents, "str") + +[] +let ``Completion list on union case type at declaration site contains modules and types but not keywords or functions``() = + let fileContents = """ +type A = + | Case of blah: int * str: l +""" + VerifyCompletionList(fileContents, "str: l", ["LanguagePrimitives"; "List"], ["let"; "log"]) + +[] +let ``Completion list on union case type at declaration site contains modules and types but not keywords or functions2``() = + let fileContents = """ +type A = + | Case of l +""" + VerifyCompletionList(fileContents, "of l", ["LanguagePrimitives"; "List"], ["let"; "log"]) + +[] +let ``No completion on enum case identifier at declaration site``() = + let fileContents = """ +type A = + | C = 0 +""" + VerifyNoCompletionList(fileContents, "| C") + #if EXE ShouldDisplaySystemNamespace() #endif From 8b0051bd613679ecbe24672271576fcba483121c Mon Sep 17 00:00:00 2001 From: kerams Date: Mon, 15 Nov 2021 15:07:10 +0100 Subject: [PATCH 3/8] Remove undesirable tests --- .../Tests.LanguageService.Completion.fs | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs index 6b9eda12e1a..c59602db4cd 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs @@ -4257,38 +4257,6 @@ let x = query { for bbbb in abbbbc(*D0*) do [ "Contains" ] // should contain [ ] // should not contain - [] - member public this.``InDeclaration.Bug3176a``() = - AssertCtrlSpaceCompleteContains - [ "type T<'a> = { aaaa : 'a; bbbb : int } " ] - "aa" // marker - [ "aaaa" ] // should contain - [ "bbbb" ] // should not contain - - [] - member public this.``InDeclaration.Bug3176b``() = - AssertCtrlSpaceCompleteContains - [ "type T<'a> = { aaaa : 'a; bbbb : int } " ] - "bb" // marker - [ "bbbb" ] // should contain - [ "aaaa" ] // should not contain - - [] - member public this.``InDeclaration.Bug3176c``() = - AssertCtrlSpaceCompleteContains - [ "type C ="; - " val aaaa: int" ] - "aa" // move to marker - ["aaaa"] [] // should contain 'aaaa' - - [] - member public this.``InDeclaration.Bug3176d``() = - AssertCtrlSpaceCompleteContains - [ "type DU<'a> ="; - " | DULabel of 'a" ] - "DULab" // move to marker - ["DULabel"] [] // should contain 'DULabel' - [] member public this.``IncompleteIfClause.Bug4594``() = AssertCtrlSpaceCompleteContains From 0e2b4d7206bc88166a6ccb2a0f6eb90b6b175eae Mon Sep 17 00:00:00 2001 From: kerams Date: Thu, 16 Dec 2021 14:57:40 +0100 Subject: [PATCH 4/8] Update surface area, constrain type alias completions --- src/fsharp/service/FSharpCheckerResults.fs | 2 ++ src/fsharp/service/ServiceParsedInputOps.fs | 5 +++++ src/fsharp/service/ServiceParsedInputOps.fsi | 2 ++ ...mpilerService.SurfaceArea.netstandard.expected | 15 +++++++++++++++ .../tests/UnitTests/CompletionProviderTests.fs | 7 +++++++ 5 files changed, 31 insertions(+) diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 8afaf57b856..252ca38d226 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1028,6 +1028,8 @@ type internal TypeCheckInfo | Some CompletionContext.PatternType // Completion at '| Case1 of ...' | Some CompletionContext.UnionCaseFieldsDeclaration + // Completion at 'type Long = int6...' + | Some CompletionContext.TypeAbbreviation // Completion at 'Field1: ...' | Some(CompletionContext.RecordField(RecordContext.Declaration false)) -> GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors, resolveOverloads, false, getAllSymbols) diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index 06136b7f7ba..60a0e555e84 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -73,6 +73,8 @@ type CompletionContext = /// Completing union case fields declaration (e.g. 'A of stri|' but not 'B of tex|: string') | UnionCaseFieldsDeclaration + | TypeAbbreviation + type ShortIdent = string type ShortIdents = ShortIdent[] @@ -1104,6 +1106,9 @@ module ParsedInput = member _.VisitEnumDefn(_path, _, range) = if rangeContainsPos range pos then Some CompletionContext.Invalid else None + + member _.VisitTypeAbbrev(_path, _, range) = + if rangeContainsPos range pos then Some CompletionContext.TypeAbbreviation else None } SyntaxTraversal.Traverse(pos, parsedInput, walker) diff --git a/src/fsharp/service/ServiceParsedInputOps.fsi b/src/fsharp/service/ServiceParsedInputOps.fsi index 21c9e06a726..223823ac05e 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fsi +++ b/src/fsharp/service/ServiceParsedInputOps.fsi @@ -48,6 +48,8 @@ type public CompletionContext = /// Completing union case fields declaration (e.g. 'A of stri|' but not 'B of tex|: string') | UnionCaseFieldsDeclaration + | TypeAbbreviation + type public ModuleKind = { IsAutoOpen: bool HasModuleSuffix: bool } diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 49201d40170..cc66165c45e 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -2440,6 +2440,8 @@ FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 ParameterList FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 PatternType FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RangeOperator FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RecordField +FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 TypeAbbreviation +FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 UnionCaseFieldsDeclaration FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(FSharp.Compiler.EditorServices.CompletionContext) FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(System.Object, System.Collections.IEqualityComparer) @@ -2451,6 +2453,8 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean IsParameterList FSharp.Compiler.EditorServices.CompletionContext: Boolean IsPatternType FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRangeOperator FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRecordField +FSharp.Compiler.EditorServices.CompletionContext: Boolean IsTypeAbbreviation +FSharp.Compiler.EditorServices.CompletionContext: Boolean IsUnionCaseFieldsDeclaration FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsAttributeApplication() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsInherit() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsInvalid() @@ -2459,6 +2463,8 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsParameterList() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsPatternType() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRangeOperator() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRecordField() +FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsTypeAbbreviation() +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 FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewInherit(FSharp.Compiler.EditorServices.InheritanceContext, System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]]) @@ -2467,10 +2473,14 @@ FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewRecordField(FSharp.Compiler.EditorServices.RecordContext) FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext PatternType FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext RangeOperator +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext TypeAbbreviation +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext UnionCaseFieldsDeclaration FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_AttributeApplication() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_Invalid() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_PatternType() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_RangeOperator() +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_TypeAbbreviation() +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_UnionCaseFieldsDeclaration() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+Inherit FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+OpenDeclaration FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+ParameterList @@ -3476,21 +3486,26 @@ FSharp.Compiler.EditorServices.RecordContext+New: System.Tuple`2[Microsoft.FShar FSharp.Compiler.EditorServices.RecordContext+New: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]] path FSharp.Compiler.EditorServices.RecordContext+Tags: Int32 Constructor FSharp.Compiler.EditorServices.RecordContext+Tags: Int32 CopyOnUpdate +FSharp.Compiler.EditorServices.RecordContext+Tags: Int32 Declaration FSharp.Compiler.EditorServices.RecordContext+Tags: Int32 New FSharp.Compiler.EditorServices.RecordContext: Boolean Equals(FSharp.Compiler.EditorServices.RecordContext) FSharp.Compiler.EditorServices.RecordContext: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.RecordContext: Boolean Equals(System.Object, System.Collections.IEqualityComparer) FSharp.Compiler.EditorServices.RecordContext: Boolean IsConstructor FSharp.Compiler.EditorServices.RecordContext: Boolean IsCopyOnUpdate +FSharp.Compiler.EditorServices.RecordContext: Boolean IsDeclaration FSharp.Compiler.EditorServices.RecordContext: Boolean IsNew FSharp.Compiler.EditorServices.RecordContext: Boolean get_IsConstructor() FSharp.Compiler.EditorServices.RecordContext: Boolean get_IsCopyOnUpdate() +FSharp.Compiler.EditorServices.RecordContext: Boolean get_IsDeclaration() FSharp.Compiler.EditorServices.RecordContext: Boolean get_IsNew() FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext NewConstructor(System.String) FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext NewCopyOnUpdate(FSharp.Compiler.Text.Range, System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]]) +FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext NewDeclaration(Boolean) FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext NewNew(System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]]) FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext+Constructor FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext+CopyOnUpdate +FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext+Declaration FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext+New FSharp.Compiler.EditorServices.RecordContext: FSharp.Compiler.EditorServices.RecordContext+Tags FSharp.Compiler.EditorServices.RecordContext: Int32 GetHashCode() diff --git a/vsintegration/tests/UnitTests/CompletionProviderTests.fs b/vsintegration/tests/UnitTests/CompletionProviderTests.fs index b1cfc635610..0f362943d66 100644 --- a/vsintegration/tests/UnitTests/CompletionProviderTests.fs +++ b/vsintegration/tests/UnitTests/CompletionProviderTests.fs @@ -782,6 +782,13 @@ type A = """ VerifyCompletionList(fileContents, "of l", ["LanguagePrimitives"; "List"], ["let"; "log"]) +[] +let ``Completion list on type alias contains modules and types but not keywords or functions``() = + let fileContents = """ +type A = l +""" + VerifyCompletionList(fileContents, "= l", ["LanguagePrimitives"; "List"], ["let"; "log"]) + [] let ``No completion on enum case identifier at declaration site``() = let fileContents = """ From f802432e91a4dd6c4d32e8a706c9fdd62d8a4ebd Mon Sep 17 00:00:00 2001 From: kerams Date: Thu, 16 Dec 2021 15:35:28 +0100 Subject: [PATCH 5/8] Fix surface area --- .../FSharp.CompilerService.SurfaceArea.netstandard.expected | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index cc66165c45e..d9be45e9c97 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -3482,6 +3482,8 @@ FSharp.Compiler.EditorServices.RecordContext+CopyOnUpdate: FSharp.Compiler.Text. FSharp.Compiler.EditorServices.RecordContext+CopyOnUpdate: FSharp.Compiler.Text.Range range FSharp.Compiler.EditorServices.RecordContext+CopyOnUpdate: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]] get_path() FSharp.Compiler.EditorServices.RecordContext+CopyOnUpdate: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]] path +FSharp.Compiler.EditorServices.RecordContext+Declaration: Boolean get_isInIdentifier() +FSharp.Compiler.EditorServices.RecordContext+Declaration: Boolean isInIdentifier FSharp.Compiler.EditorServices.RecordContext+New: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]] get_path() FSharp.Compiler.EditorServices.RecordContext+New: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[System.String],Microsoft.FSharp.Core.FSharpOption`1[System.String]] path FSharp.Compiler.EditorServices.RecordContext+Tags: Int32 Constructor From b029a0ccac6328f8e040cdb2db3f329fd2494e8d Mon Sep 17 00:00:00 2001 From: kerams Date: Fri, 17 Dec 2021 13:33:23 +0100 Subject: [PATCH 6/8] Address comments --- src/fsharp/service/FSharpCheckerResults.fs | 4 ++-- src/fsharp/service/ServiceParsedInputOps.fs | 23 +++++++++++++++----- src/fsharp/service/ServiceParsedInputOps.fsi | 4 +++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 252ca38d226..d45c277e5b5 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1028,8 +1028,8 @@ type internal TypeCheckInfo | Some CompletionContext.PatternType // Completion at '| Case1 of ...' | Some CompletionContext.UnionCaseFieldsDeclaration - // Completion at 'type Long = int6...' - | Some CompletionContext.TypeAbbreviation + // Completion at 'type Long = int6...' or 'type SomeUnion = Abc...' + | Some CompletionContext.TypeAbbreviationOrSingleCaseUnion // Completion at 'Field1: ...' | Some(CompletionContext.RecordField(RecordContext.Declaration false)) -> GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors, resolveOverloads, false, getAllSymbols) diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index 60a0e555e84..badc3abb0ff 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -73,7 +73,9 @@ type CompletionContext = /// Completing union case fields declaration (e.g. 'A of stri|' but not 'B of tex|: string') | UnionCaseFieldsDeclaration - | TypeAbbreviation + /// Completing a type abbreviation (e.g. type Long = int6|) + /// or a single case union without a bar (type SomeUnion = Abc|) + | TypeAbbreviationOrSingleCaseUnion type ShortIdent = string @@ -1028,7 +1030,8 @@ module ParsedInput = Some CompletionContext.Invalid | _ -> defaultTraverse synBinding - member _.VisitHashDirective (_path, _directive, range) = + member _.VisitHashDirective (_path, _directive, range) = + // No completions in a directive if rangeContainsPos range pos then Some CompletionContext.Invalid else None @@ -1037,11 +1040,15 @@ module ParsedInput = | Some lastIdent when pos.Line = lastIdent.idRange.EndLine && lastIdent.idRange.EndColumn >= 0 && pos.Column <= lineStr.Length -> let stringBetweenModuleNameAndPos = lineStr.[lastIdent.idRange.EndColumn..pos.Column - 1] if stringBetweenModuleNameAndPos |> Seq.forall (fun x -> x = ' ' || x = '.') then + // No completions in a top level a module or namespace identifier Some CompletionContext.Invalid else None | _ -> None - member _.VisitComponentInfo(_path, SynComponentInfo(range = range)) = + member _.VisitComponentInfo(_path, SynComponentInfo(range = range)) = + // No completions in component info (unless it's within an attribute) + // /// XmlDo| + // type R = class end if rangeContainsPos range pos then Some CompletionContext.Invalid else None @@ -1052,9 +1059,12 @@ module ParsedInput = member _.VisitSimplePats (_path, pats) = pats |> List.tryPick (fun pat -> + // No completions in an identifier or type in a pattern match pat with + // fun x| = | SynSimplePat.Id(range = range) - | SynSimplePat.Typed(SynSimplePat.Id(range = range), _, _) when rangeContainsPos range pos -> + // fun (x: int|) = + | SynSimplePat.Typed(SynSimplePat.Id(range = range), _, _) when rangeContainsPos range pos -> Some CompletionContext.Invalid | _ -> None) @@ -1094,21 +1104,24 @@ module ParsedInput = member _.VisitUnionDefn(_path, cases, _range) = cases |> List.tryPick (fun (SynUnionCase (ident = id; caseType = caseType)) -> if rangeContainsPos id.idRange pos then + // No completions in a union case identifier Some CompletionContext.Invalid else match caseType with | SynUnionCaseKind.Fields fieldCases -> fieldCases |> List.tryPick (fun (SynField (idOpt = fieldIdOpt; range = fieldRange)) -> match fieldIdOpt with + // No completions in a union case field identifier | Some id when rangeContainsPos id.idRange pos -> Some CompletionContext.Invalid | _ -> if rangeContainsPos fieldRange pos then Some CompletionContext.UnionCaseFieldsDeclaration else None) | _ -> None) member _.VisitEnumDefn(_path, _, range) = + // No completions anywhere in an enum if rangeContainsPos range pos then Some CompletionContext.Invalid else None member _.VisitTypeAbbrev(_path, _, range) = - if rangeContainsPos range pos then Some CompletionContext.TypeAbbreviation else None + if rangeContainsPos range pos then Some CompletionContext.TypeAbbreviationOrSingleCaseUnion else None } SyntaxTraversal.Traverse(pos, parsedInput, walker) diff --git a/src/fsharp/service/ServiceParsedInputOps.fsi b/src/fsharp/service/ServiceParsedInputOps.fsi index 223823ac05e..2180b700416 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fsi +++ b/src/fsharp/service/ServiceParsedInputOps.fsi @@ -48,7 +48,9 @@ type public CompletionContext = /// Completing union case fields declaration (e.g. 'A of stri|' but not 'B of tex|: string') | UnionCaseFieldsDeclaration - | TypeAbbreviation + /// Completing a type abbreviation (e.g. type Long = int6|) + /// or a single case union without a bar (type SomeUnion = Abc|) + | TypeAbbreviationOrSingleCaseUnion type public ModuleKind = { IsAutoOpen: bool From e529cc6a1b5b09fac17a546d4e84978b1d2302af Mon Sep 17 00:00:00 2001 From: kerams Date: Fri, 17 Dec 2021 13:36:47 +0100 Subject: [PATCH 7/8] Update ServiceParsedInputOps.fs --- src/fsharp/service/ServiceParsedInputOps.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index badc3abb0ff..a3605285ae2 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -1061,9 +1061,9 @@ module ParsedInput = pats |> List.tryPick (fun pat -> // No completions in an identifier or type in a pattern match pat with - // fun x| = + // fun x| -> | SynSimplePat.Id(range = range) - // fun (x: int|) = + // fun (x: int|) -> | SynSimplePat.Typed(SynSimplePat.Id(range = range), _, _) when rangeContainsPos range pos -> Some CompletionContext.Invalid | _ -> None) From ea4e2bfde06d268943ec66bc57d561c44f56b267 Mon Sep 17 00:00:00 2001 From: kerams Date: Fri, 17 Dec 2021 13:53:06 +0100 Subject: [PATCH 8/8] Update FSharp.CompilerService.SurfaceArea.netstandard.expected --- ...rp.CompilerService.SurfaceArea.netstandard.expected | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index d9be45e9c97..238a7e1432b 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -2440,7 +2440,7 @@ FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 ParameterList FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 PatternType FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RangeOperator FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RecordField -FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 TypeAbbreviation +FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 TypeAbbreviationOrSingleCaseUnion FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 UnionCaseFieldsDeclaration FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(FSharp.Compiler.EditorServices.CompletionContext) FSharp.Compiler.EditorServices.CompletionContext: Boolean Equals(System.Object) @@ -2453,7 +2453,7 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean IsParameterList FSharp.Compiler.EditorServices.CompletionContext: Boolean IsPatternType FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRangeOperator FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRecordField -FSharp.Compiler.EditorServices.CompletionContext: Boolean IsTypeAbbreviation +FSharp.Compiler.EditorServices.CompletionContext: Boolean IsTypeAbbreviationOrSingleCaseUnion FSharp.Compiler.EditorServices.CompletionContext: Boolean IsUnionCaseFieldsDeclaration FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsAttributeApplication() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsInherit() @@ -2463,7 +2463,7 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsParameterList() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsPatternType() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRangeOperator() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRecordField() -FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsTypeAbbreviation() +FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsTypeAbbreviationOrSingleCaseUnion() 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 @@ -2473,13 +2473,13 @@ FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewRecordField(FSharp.Compiler.EditorServices.RecordContext) FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext PatternType FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext RangeOperator -FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext TypeAbbreviation +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext TypeAbbreviationOrSingleCaseUnion FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext UnionCaseFieldsDeclaration FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_AttributeApplication() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_Invalid() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_PatternType() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_RangeOperator() -FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_TypeAbbreviation() +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_TypeAbbreviationOrSingleCaseUnion() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext get_UnionCaseFieldsDeclaration() FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+Inherit FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+OpenDeclaration