Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita54abbf

Browse files
forkiKevinRansom
authored andcommitted
Suggest Unions and Records if qualified access required (dotnet#2203)
* Suggestion union types that require qualified access* Suggestion record types that require qualified access
1 parent1fb8a75 commita54abbf

File tree

8 files changed

+100
-37
lines changed

8 files changed

+100
-37
lines changed

‎src/fsharp/ErrorResolutionHints.fs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ let FilterPredictions (userEntered:string) (suggestionF:ErrorLogger.Suggestions)
2828
if suggestion= userEnteredthen Noneelse
2929
letsuggestedText= suggestion.ToUpperInvariant()
3030
letsimilarity= Internal.Utilities.EditDistance.JaroWinklerDistance uppercaseText suggestedText
31-
if similarity>= highConfidenceThresholdthen
31+
if similarity>= highConfidenceThreshold|| suggestion.EndsWith("."+ userEntered)then
3232
Some(similarity,suggestion)
3333
elif similarity< minThresholdForSuggestions&& suggestedText.Length> minStringLengthForThresholdthen
3434
None

‎src/fsharp/NameResolution.fs‎

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,7 +2301,24 @@ let rec ResolveExprLongIdentPrim sink (ncenv:NameResolver) fullyQualified m ad n
23012301
|> Seq.map(fun e-> e.Value.DisplayName)
23022302
|> Set.ofSeq
23032303

2304-
Set.union suggestedNames suggestedTypes
2304+
letunions=
2305+
// check if the user forgot to use qualified access
2306+
nenv.eTyconsByDemangledNameAndArity
2307+
|> Seq.choose(fun e->
2308+
lethasRequireQualifiedAccessAttribute= HasFSharpAttribute ncenv.g ncenv.g.attrib_RequireQualifiedAccessAttribute e.Value.Attribs
2309+
ifnot hasRequireQualifiedAccessAttributethen
2310+
None
2311+
else
2312+
if e.Value.IsUnionTycon&& e.Value.UnionCasesArray|> Array.exists(fun c-> c.DisplayName= id.idText)then
2313+
Some e.Value
2314+
else
2315+
None)
2316+
|> Seq.map(fun t-> t.DisplayName+"."+ id.idText)
2317+
|> Set.ofSeq
2318+
2319+
suggestedNames
2320+
|> Set.union suggestedTypes
2321+
|> Set.union unions
23052322

23062323
raze(UndefinedName(0,FSComp.SR.undefinedNameValueOfConstructor,id,suggestNamesAndTypes))
23072324
ForceRaise failingCase
@@ -2881,34 +2898,51 @@ let SuggestOtherLabelsOfSameRecordType g (nenv:NameResolutionEnv) typ (id:Ident)
28812898
Set.difference labelsOfPossibleRecord givenFields
28822899

28832900

2884-
letSuggestLabelsOfRelatedRecords(nenv:NameResolutionEnv)(id:Ident)(allFields:Ident list)=
2885-
letsuggestLabels()=
2901+
letSuggestLabelsOfRelatedRecordsg(nenv:NameResolutionEnv)(id:Ident)(allFields:Ident list)=
2902+
letsuggestLabels()=
28862903
letgivenFields= allFields|> List.map(fun fld-> fld.idText)|> List.filter((<>) id.idText)|> Set.ofList
2887-
if Set.isEmpty givenFieldsthen
2888-
// return labels from all records
2889-
NameMap.domainL nenv.eFieldLabels|> Set.ofList|> Set.remove"contents"
2890-
else
2891-
letpossibleRecords=
2892-
[for fldin givenFieldsdo
2893-
match Map.tryFind fld nenv.eFieldLabelswith
2894-
| None->()
2895-
| Some recordTypes->yield!(recordTypes|> List.map(fun r-> r.TyconRef.DisplayName, fld))]
2896-
|> List.groupBy fst
2897-
|> List.map(fun(r,fields)-> r, fields|> List.map snd|> Set.ofList)
2898-
|> List.filter(fun(_,fields)-> Set.isSubset givenFields fields)
2899-
|> List.map fst
2900-
|> Set.ofList
2901-
2902-
letlabelsOfPossibleRecords=
2903-
nenv.eFieldLabels
2904-
|> Seq.filter(fun kv->
2905-
kv.Value
2906-
|> List.map(fun r-> r.TyconRef.DisplayName)
2907-
|> List.exists possibleRecords.Contains)
2908-
|> Seq.map(fun kv-> kv.Key)
2909-
|> Set.ofSeq
2904+
letfullyQualfied=
2905+
if Set.isEmpty givenFieldsthen
2906+
// return labels from all records
2907+
NameMap.domainL nenv.eFieldLabels|> Set.ofList|> Set.remove"contents"
2908+
else
2909+
letpossibleRecords=
2910+
[for fldin givenFieldsdo
2911+
match Map.tryFind fld nenv.eFieldLabelswith
2912+
| None->()
2913+
| Some recordTypes->yield!(recordTypes|> List.map(fun r-> r.TyconRef.DisplayName, fld))]
2914+
|> List.groupBy fst
2915+
|> List.map(fun(r,fields)-> r, fields|> List.map snd|> Set.ofList)
2916+
|> List.filter(fun(_,fields)-> Set.isSubset givenFields fields)
2917+
|> List.map fst
2918+
|> Set.ofList
29102919

2911-
Set.difference labelsOfPossibleRecords givenFields
2920+
letlabelsOfPossibleRecords=
2921+
nenv.eFieldLabels
2922+
|> Seq.filter(fun kv->
2923+
kv.Value
2924+
|> List.map(fun r-> r.TyconRef.DisplayName)
2925+
|> List.exists possibleRecords.Contains)
2926+
|> Seq.map(fun kv-> kv.Key)
2927+
|> Set.ofSeq
2928+
2929+
Set.difference labelsOfPossibleRecords givenFields
2930+
2931+
ifnot(Set.isEmpty fullyQualfied)then fullyQualfiedelse
2932+
2933+
// check if the user forgot to use qualified access
2934+
nenv.eTyconsByDemangledNameAndArity
2935+
|> Seq.choose(fun e->
2936+
lethasRequireQualifiedAccessAttribute= HasFSharpAttribute g g.attrib_RequireQualifiedAccessAttribute e.Value.Attribs
2937+
ifnot hasRequireQualifiedAccessAttributethen
2938+
None
2939+
else
2940+
if e.Value.IsRecordTycon&& e.Value.AllFieldsArray|> Seq.exists(fun x-> x.Name= id.idText)then
2941+
Some e.Value
2942+
else
2943+
None)
2944+
|> Seq.map(fun t-> t.DisplayName+"."+ id.idText)
2945+
|> Set.ofSeq
29122946

29132947
UndefinedName(0,FSComp.SR.undefinedNameRecordLabel, id, suggestLabels)
29142948

@@ -2924,7 +2958,7 @@ let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ (mp,id:Ident) allFields =
29242958
try Map.find id.idText nenv.eFieldLabels
29252959
with:? KeyNotFoundException->
29262960
// record label is unknown -> suggest related labels and give a hint to the user
2927-
error(SuggestLabelsOfRelatedRecords nenv id allFields)
2961+
error(SuggestLabelsOfRelatedRecordsgnenv id allFields)
29282962

29292963
// Eliminate duplicates arising from multiple 'open'
29302964
frefs

‎src/fsharp/TypeChecker.fs‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12769,12 +12769,16 @@ module MutRecBindingChecking =
1276912769
// Class members can access protected members of the implemented type
1277012770
// Class members can access private members in the typ
1277112771
let isExtrinsic = (declKind = ExtrinsicExtensionBinding)
12772-
letenvForTycon = MakeInnerEnvForTyconRef cenv envForDecls tcref isExtrinsic
12772+
letinnitalEnvForTycon = MakeInnerEnvForTyconRef cenv envForDecls tcref isExtrinsic
1277312773

1277412774
// Re-add the type constructor to make it take precedence for record label field resolutions
1277512775
// This does not apply to extension members: in those cases the relationship between the record labels
1277612776
// and the type is too extruded
12777-
let envForTycon = if isExtrinsic then envForTycon else AddLocalTyconRefs true cenv.g cenv.amap tcref.Range [tcref] envForTycon
12777+
let envForTycon =
12778+
if isExtrinsic then
12779+
innitalEnvForTycon
12780+
else
12781+
AddLocalTyconRefs true cenv.g cenv.amap tcref.Range [tcref] innitalEnvForTycon
1277812782

1277912783
// Make fresh version of the class type for type checking the members and lets *
1278012784
let _,copyOfTyconTypars,_,objTy,thisTy = FreshenObjectArgType cenv tcref.Range TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars

‎tests/fsharp/typecheck/sigs/neg07.bsl‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,25 @@ neg07.fs(7,10,7,29): typecheck error FS0049: Uppercase variable identifiers shou
33

44
neg07.fs(7,10,7,29): typecheck error FS0049: Uppercase variable identifiers shouldnot generally be usedin patterns,and may indicate a misspelt pattern name.
55

6-
neg07.fs(24,13,24,23): typecheck error FS0039: The valueor constructor 'UnionCase1' isnot defined.
6+
neg07.fs(24,13,24,23): typecheck error FS0039: The valueor constructor 'UnionCase1' isnot defined. Maybe you want one of the following: X.UnionCase1
77

88
neg07.fs(27,11,27,21): typecheck error FS0049: Uppercase variable identifiers shouldnot generally be usedin patterns,and may indicate a misspelt pattern name.
99

1010
neg07.fs(28,11,28,21): typecheck error FS0049: Uppercase variable identifiers shouldnot generally be usedin patterns,and may indicate a misspelt pattern name.
1111

1212
neg07.fs(28,11,28,21): typecheck error FS0026: This rule will never be matched
1313

14-
neg07.fs(31,18,31,28): typecheck error FS0039: The valueor constructor 'UnionCase1' isnot defined.
14+
neg07.fs(31,18,31,28): typecheck error FS0039: The valueor constructor 'UnionCase1' isnot defined. Maybe you want one of the following: X.UnionCase1
1515

1616
neg07.fs(35,11,35,21): typecheck error FS0049: Uppercase variable identifiers shouldnot generally be usedin patterns,and may indicate a misspelt pattern name.
1717

1818
neg07.fs(36,11,36,21): typecheck error FS0049: Uppercase variable identifiers shouldnot generally be usedin patterns,and may indicate a misspelt pattern name.
1919

2020
neg07.fs(36,11,36,21): typecheck error FS0026: This rule will never be matched
2121

22-
neg07.fs(46,15,46,27): typecheck error FS0039: The record label 'RecordLabel1' isnot defined.
22+
neg07.fs(46,15,46,27): typecheck error FS0039: The record label 'RecordLabel1' isnot defined. Maybe you want one of the following: R.RecordLabel1
2323

24-
neg07.fs(47,19,47,31): typecheck error FS0039: The record label 'RecordLabel1' isnot defined.
24+
neg07.fs(47,19,47,31): typecheck error FS0039: The record label 'RecordLabel1' isnot defined. Maybe you want one of the following: R.RecordLabel1
2525

2626
neg07.fs(57,10,57,17): typecheck error FS1196: The 'UseNullAsTrueValue' attribute flag may only be used with union types that have one nullary caseand at least one non-nullary case
2727

‎tests/fsharpqa/Source/Conformance/InferenceProcedures/NameResolution/RequireQualifiedAccess/E_OnRecord.fs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Verify error when not fully qualifying a record field when it
33
// has the RequireQualifiedAccess attribute.
44

5-
//<Expects status="error">The record label 'Field1' is not defined\.$</Expects>
6-
//<Expects status="error">The record label 'Field1' is not defined\.$</Expects>
5+
//<Expects status="error">The record label 'Field1' is not defined\.</Expects>
6+
//<Expects status="error">The record label 'Field1' is not defined\.</Expects>
77

88
[<RequireQualifiedAccess>]
99
typeR={ Field1:int; Field2:string}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// #Warnings
2+
//<Expects status="Error" id="FS0039">The record label 'Field1' is not defined. Maybe you want one of the following: MyRecord.Field1$</Expects>
3+
4+
[<RequireQualifiedAccess>]
5+
typeMyRecord={
6+
Field1:string
7+
Field2:int
8+
}
9+
10+
letr={ Field1="hallo"; Field2=1}
11+
12+
exit0
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// #Warnings
2+
//<Expects status="Error" id="FS0039">The value or constructor 'MyCase1' is not defined. Maybe you want one of the following: MyUnion.MyCase1$</Expects>
3+
4+
[<RequireQualifiedAccess>]
5+
typeMyUnion=
6+
| MyCase1
7+
| MyCase2ofstring
8+
9+
letx:MyUnion= MyCase1
10+
11+
exit0

‎tests/fsharpqa/Source/Warnings/env.lst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
SOURCE=SuggestModules.fs # SuggestModules.fs
2929
SOURCE=SuggestMethods.fs # SuggestMethods.fs
3030
SOURCE=SuggestAttributes.fs # SuggestAttributes.fs
31+
SOURCE=SuggestUnionTypeForRQAUnions.fs SCFLAGS="--vserrors" # SuggestUnionTypeForRQAUnions.fs
32+
SOURCE=SuggestRecordTypeForRQARecords.fs SCFLAGS="--vserrors" # SuggestRecordTypeForRQARecords.fs
3133
SOURCE=SuggestRecordLabels.fs SCFLAGS="--vserrors" # SuggestRecordLabels.fs
3234
SOURCE=SuggestUnionCases.fs SCFLAGS="--vserrors" # SuggestUnionCases.fs
3335
SOURCE=SuggestArrayModuleFunctions.fs SCFLAGS="--vserrors" # SuggestArrayModuleFunctions.fs

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp