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

Commit9e02e7f

Browse files
forkiKevinRansom
authored andcommitted
Suggestions for spelling mistakes needs to be filtered much stronger (dotnet#2175)
* Use EditDistance for threshold* Don't throw too specific error message* Suggest more types* Suggest vals and exns* Oupsi
1 parenta0570e2 commit9e02e7f

File tree

36 files changed

+272
-116
lines changed

36 files changed

+272
-116
lines changed

‎src/fsharp/ErrorResolutionHints.fs‎

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,36 @@
44
moduleinternalMicrosoft.FSharp.Compiler.ErrorResolutionHints
55

66
letmaxSuggestions=5
7-
7+
letminThresholdForSuggestions=0.7
8+
lethighConfidenceThreshold=0.85
89
letminStringLengthForThreshold=3
910

10-
letthresholdForSuggestions=0.7
11+
/// We report a candidate if its edit distance is <= the threshold.
12+
/// The threshhold is set to about a quarter of the number of characters the user entered.
13+
letIsInEditDistanceProximity userEntered suggestion=
14+
leteditDistance= Internal.Utilities.EditDistance.CalcEditDistance(userEntered,suggestion)
15+
letthreshold=
16+
match userEntered.Lengthwith
17+
| xwhen x<5->1
18+
| xwhen x<7->2
19+
| x-> x/4+1
20+
21+
editDistance<= threshold
1122

1223
/// Filters predictions based on edit distance to the given unknown identifier.
13-
letFilterPredictions(unknownIdent:string)(predictionsF:ErrorLogger.Suggestions)=
14-
letunknownIdent= unknownIdent.ToUpperInvariant()
15-
letuseThreshold= unknownIdent.Length>= minStringLengthForThreshold
16-
predictionsF()
17-
|> Seq.choose(fun p->
18-
letsimilarity= Internal.Utilities.EditDistance.JaroWinklerDistance unknownIdent(p.ToUpperInvariant())
19-
ifnot useThreshold|| similarity>= thresholdForSuggestions|| p.Contains unknownIdentthen
20-
Some(similarity,p)
24+
letFilterPredictions(userEntered:string)(suggestionF:ErrorLogger.Suggestions)=
25+
letuppercaseText= userEntered.ToUpperInvariant()
26+
suggestionF()
27+
|> Seq.choose(fun suggestion->
28+
if suggestion= userEnteredthen Noneelse
29+
letsuggestedText= suggestion.ToUpperInvariant()
30+
letsimilarity= Internal.Utilities.EditDistance.JaroWinklerDistance uppercaseText suggestedText
31+
if similarity>= highConfidenceThresholdthen
32+
Some(similarity,suggestion)
33+
elif similarity< minThresholdForSuggestions&& suggestedText.Length> minStringLengthForThresholdthen
34+
None
35+
elif IsInEditDistanceProximity uppercaseText suggestedTextthen
36+
Some(similarity,suggestion)
2137
else
2238
None)
2339
|> Seq.sortByDescending fst

‎src/fsharp/FSComp.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ undefinedNameTypeIn,"The type '%s' is not defined in '%s'."
1313
undefinedNameRecordLabelOrNamespace,"The record label or namespace '%s' is not defined."
1414
undefinedNameRecordLabel,"The record label '%s' is not defined."
1515
undefinedNameSuggestionsIntro,"Maybe you want one of the following:"
16-
undefinedNameTypeParameter,"The type parameter'%s is not defined."
16+
undefinedNameTypeParameter,"The type parameter %s is not defined."
1717
undefinedNamePatternDiscriminator,"The pattern discriminator '%s' is not defined."
1818
replaceWithSuggestion,"Replace with '%s'"
1919
missingElseBranch,"The 'if' expression is missing an 'else' branch. The 'then' branch has type '%s'. Because 'if' is an expression, and not a statement, add an 'else' branch which returns a value of the same type."

‎src/fsharp/FSharp.Compiler.Unittests/EditDistance.fs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@ module EditDistance =
1616
[<TestCase("DWAYNE","DUANE", ExpectedResult="0.840")>]
1717
[<TestCase("DIXON","DICKSONX", ExpectedResult="0.813")>]
1818
letJaroWinklerTest(str1:string,str2:string):string=
19-
String.Format("{0:0.000}", JaroWinklerDistance str1 str2)
19+
String.Format("{0:0.000}", JaroWinklerDistance str1 str2)
20+
21+
[<Test>]
22+
[<TestCase("RICK","RICK", ExpectedResult=0)>]
23+
[<TestCase("MARTHA","MARHTA", ExpectedResult=1)>]
24+
[<TestCase("'T","'u", ExpectedResult=1)>]
25+
letEditDistanceTest(str1:string,str2:string):int=
26+
CalcEditDistance(str1,str2)

‎src/fsharp/NameResolution.fs‎

Lines changed: 95 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,7 +1661,7 @@ let rec ResolveLongIndentAsModuleOrNamespace atMostOne amap m fullyQualified (ne
16611661
moduleOrNamespaces
16621662
|> Seq.collect(fun kv-> kv.Value)
16631663
|> Seq.filter(fun modref-> IsEntityAccessible amap m ad modref)
1664-
|> Seq.map(fun e-> e.DisplayName)
1664+
|> Seq.collect(fun e->[e.DisplayName; e.DemangledModuleOrNamespaceName])
16651665
|> Set.ofSeq
16661666

16671667
UndefinedName(0,FSComp.SR.undefinedNameNamespaceOrModule,id,suggestModulesAndNamespaces))
@@ -1674,7 +1674,7 @@ let rec ResolveLongIndentAsModuleOrNamespace atMostOne amap m fullyQualified (ne
16741674
letsuggestNames()=
16751675
mty.ModulesAndNamespacesByDemangledName
16761676
|> Seq.filter(fun kv-> IsEntityAccessible amap m ad(modref.NestedTyconRef kv.Value))
1677-
|> Seq.map(fun e-> e.Value.DisplayName)
1677+
|> Seq.collect(fun e->[e.Value.DisplayName; e.Value.DemangledModuleOrNamespaceName])
16781678
|> Set.ofSeq
16791679

16801680
leterror= raze(UndefinedName(depth,FSComp.SR.undefinedNameNamespace,id,suggestNames))
@@ -2152,7 +2152,7 @@ let rec ResolveExprLongIdentInModuleOrNamespace (ncenv:NameResolver) nenv (typeN
21522152

21532153
match tyconSearch+++ moduleSearch+++ unionSearchwith
21542154
| Result[]->
2155-
letsuggestPossibleTypes()=
2155+
letsuggestPossibleTypesAndNames()=
21562156
match adwith
21572157
| AccessibleFrom_->
21582158
lettypes=
@@ -2178,12 +2178,26 @@ let rec ResolveExprLongIdentInModuleOrNamespace (ncenv:NameResolver) nenv (typeN
21782178
|> Seq.map(fun uc-> uc.DisplayName)
21792179
|> Set.ofSeq
21802180

2181+
letvals=
2182+
modref.ModuleOrNamespaceType.AllValsByLogicalName
2183+
|> Seq.filter(fun e-> IsValAccessible ad(mkNestedValRef modref e.Value))
2184+
|> Seq.map(fun e-> e.Value.DisplayName)
2185+
|> Set.ofSeq
2186+
2187+
letexns=
2188+
modref.ModuleOrNamespaceType.ExceptionDefinitionsByDemangledName
2189+
|> Seq.filter(fun e-> IsTyconReprAccessible ncenv.amap m ad(modref.NestedTyconRef e.Value))
2190+
|> Seq.map(fun e-> e.Value.DisplayName)
2191+
|> Set.ofSeq
2192+
21812193
types
21822194
|> Set.union submodules
21832195
|> Set.union unions
2196+
|> Set.union vals
2197+
|> Set.union exns
21842198
|_-> Set.empty
21852199

2186-
raze(UndefinedName(depth,FSComp.SR.undefinedNameValueConstructorNamespaceOrType,id,suggestPossibleTypes))
2200+
raze(UndefinedName(depth,FSComp.SR.undefinedNameValueConstructorNamespaceOrType,id,suggestPossibleTypesAndNames))
21872201
| results-> AtMostOneResult id.idRange results
21882202

21892203
/// An identifier has resolved to a type name in an expression (corresponding to one or more TyconRefs).
@@ -2203,8 +2217,7 @@ let ChooseTyconRefInExpr (ncenv:NameResolver, m, ad, nenv, id:Ident, typeNameRes
22032217

22042218
/// Resolve F# "A.B.C" syntax in expressions
22052219
/// Not all of the sequence will necessarily be swallowed, i.e. we return some identifiers
2206-
/// that may represent further actions, e.g. further lookups.
2207-
2220+
/// that may represent further actions, e.g. further lookups.
22082221
let recResolveExprLongIdentPrim sink(ncenv:NameResolver)fullyQualified m ad nenv(typeNameResInfo:TypeNameResolutionInfo)lid=
22092222
letresInfo= ResolutionInfo.Empty
22102223
match lidwith
@@ -2267,7 +2280,6 @@ let rec ResolveExprLongIdentPrim sink (ncenv:NameResolver) fullyQualified m ad n
22672280
else
22682281
NoResultsOrUsefulErrors
22692282

2270-
22712283
ctorSearch+++ implicitOpSearch
22722284

22732285
letresInfo,item,rest=
@@ -2278,11 +2290,20 @@ let rec ResolveExprLongIdentPrim sink (ncenv:NameResolver) fullyQualified m ad n
22782290
match!typeErrorwith
22792291
| Some e-> raze e
22802292
|_->
2281-
letsuggestNames()=
2282-
nenv.eUnqualifiedItems
2283-
|> Seq.map(fun e-> e.Value.DisplayName)
2284-
|> Set.ofSeq
2285-
raze(UndefinedName(0,FSComp.SR.undefinedNameValueOfConstructor,id,suggestNames))// TODO: suggest ctors
2293+
letsuggestNamesAndTypes()=
2294+
letsuggestedNames=
2295+
nenv.eUnqualifiedItems
2296+
|> Seq.map(fun e-> e.Value.DisplayName)
2297+
|> Set.ofSeq
2298+
2299+
letsuggestedTypes=
2300+
nenv.TyconsByDemangledNameAndArity fullyQualified
2301+
|> Seq.map(fun e-> e.Value.DisplayName)
2302+
|> Set.ofSeq
2303+
2304+
Set.union suggestedNames suggestedTypes
2305+
2306+
raze(UndefinedName(0,FSComp.SR.undefinedNameValueOfConstructor,id,suggestNamesAndTypes))
22862307
ForceRaise failingCase
22872308

22882309
ResolutionInfo.SendToSink(sink,ncenv,nenv,ItemOccurence.Use,ad,resInfo,ResultTyparChecker(fun()-> CheckAllTyparsInferrable ncenv.amap m item))
@@ -2367,16 +2388,40 @@ let rec ResolveExprLongIdentPrim sink (ncenv:NameResolver) fullyQualified m ad n
23672388

23682389
search+++ moduleSearch+++ tyconSearch
23692390

2391+
letsuggestEverythingInScope()=
2392+
letsuggestedModulesAndNamespaces=
2393+
nenv.ModulesAndNamespaces fullyQualified
2394+
|> Seq.collect(fun kv-> kv.Value)
2395+
|> Seq.filter(fun modref-> IsEntityAccessible ncenv.amap m ad modref)
2396+
|> Seq.collect(fun e->[e.DisplayName; e.DemangledModuleOrNamespaceName])
2397+
|> Set.ofSeq
2398+
2399+
letsuggestedTypes=
2400+
nenv.TyconsByDemangledNameAndArity fullyQualified
2401+
|> Seq.map(fun e-> e.Value.DisplayName)
2402+
|> Set.ofSeq
2403+
2404+
letsuggestedNames=
2405+
nenv.eUnqualifiedItems
2406+
|> Seq.map(fun e-> e.Value.DisplayName)
2407+
|> Set.ofSeq
2408+
2409+
suggestedNames
2410+
|> Set.union suggestedTypes
2411+
|> Set.union suggestedModulesAndNamespaces
2412+
23702413
match innerSearchwith
2414+
| Exception(UndefinedName(0,_,id1,suggestionsF))when id.idRange= id1.idRange->
2415+
letmergeSuggestions()=
2416+
suggestEverythingInScope()
2417+
|> Set.union(suggestionsF())
2418+
2419+
letfailingCase= raze(UndefinedName(0,FSComp.SR.undefinedNameValueNamespaceTypeOrModule,id,mergeSuggestions))
2420+
ForceRaise failingCase
23712421
| Exception err-> ForceRaise(Exception err)
23722422
| Result(res::_)-> ForceRaise(Result res)
23732423
| Result[]->
2374-
letsuggestNames()=
2375-
nenv.eUnqualifiedItems
2376-
|> Seq.map(fun e-> e.Value.DisplayName)
2377-
|> Set.ofSeq
2378-
2379-
letfailingCase= raze(UndefinedName(0,FSComp.SR.undefinedNameValueNamespaceTypeOrModule,id,suggestNames))// TODO: suggest modules and types
2424+
letfailingCase= raze(UndefinedName(0,FSComp.SR.undefinedNameValueNamespaceTypeOrModule,id,suggestEverythingInScope))
23802425
ForceRaise failingCase
23812426

23822427
ResolutionInfo.SendToSink(sink,ncenv,nenv,ItemOccurence.Use,ad,resInfo,ResultTyparChecker(fun()-> CheckAllTyparsInferrable ncenv.amap m item))
@@ -2462,9 +2507,15 @@ let rec ResolvePatternLongIdentInModuleOrNamespace (ncenv:NameResolver) nenv num
24622507
letsubmodules=
24632508
mty.ModulesAndNamespacesByDemangledName
24642509
|> Seq.filter(fun kv-> IsEntityAccessible ncenv.amap m ad(modref.NestedTyconRef kv.Value))
2510+
|> Seq.collect(fun e->[e.Value.DisplayName; e.Value.DemangledModuleOrNamespaceName])
2511+
|> Set.ofSeq
2512+
2513+
letsuggestedTypes=
2514+
nenv.TyconsByDemangledNameAndArity FullyQualifiedFlag.OpenQualified
24652515
|> Seq.map(fun e-> e.Value.DisplayName)
24662516
|> Set.ofSeq
2467-
submodules// TODO: suggest types and ctors
2517+
2518+
Set.union submodules suggestedTypes
24682519
|_-> Set.empty
24692520

24702521
raze(UndefinedName(depth,FSComp.SR.undefinedNameConstructorModuleOrNamespace,id,suggestPossibleTypes))
@@ -2564,7 +2615,13 @@ let rec ResolveTypeLongIdentInTyconRefPrim (ncenv:NameResolver) (typeNameResInfo
25642615
lettcrefs= CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities(tcrefs, typeNameResInfo, genOk, m)
25652616
match tcrefswith
25662617
| tcref::_-> success tcref
2567-
|[]-> raze(UndefinedName(depth,FSComp.SR.undefinedNameType,id,NoSuggestions))// TODO: suggest types
2618+
|[]->
2619+
letsuggestTypes()=
2620+
tcref.ModuleOrNamespaceType.TypesByDemangledNameAndArity id.idRange
2621+
|> Seq.map(fun e-> e.Value.DisplayName)
2622+
|> Set.ofSeq
2623+
2624+
raze(UndefinedName(depth,FSComp.SR.undefinedNameType,id,suggestTypes))
25682625
| id::rest->
25692626
#if EXTENSIONTYPING
25702627
// No dotting through type generators to get to a nested type!
@@ -2579,7 +2636,13 @@ let rec ResolveTypeLongIdentInTyconRefPrim (ncenv:NameResolver) (typeNameResInfo
25792636
lettcrefs= CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities(tcrefs, typeNameResInfo.DropStaticArgsInfo, genOk, m)
25802637
match tcrefswith
25812638
|_::_-> tcrefs|> CollectAtMostOneResult(fun(resInfo,tcref)-> ResolveTypeLongIdentInTyconRefPrim ncenv typeNameResInfo ad resInfo genOk(depth+1) m tcref rest)
2582-
|[]-> raze(UndefinedName(depth,FSComp.SR.undefinedNameType,id,NoSuggestions))// TODO: suggest types
2639+
|[]->
2640+
letsuggestTypes()=
2641+
tcref.ModuleOrNamespaceType.TypesByDemangledNameAndArity id.idRange
2642+
|> Seq.map(fun e-> e.Value.DisplayName)
2643+
|> Set.ofSeq
2644+
2645+
raze(UndefinedName(depth,FSComp.SR.undefinedNameType,id,suggestTypes))
25832646

25842647
AtMostOneResult m tyconSearch
25852648

@@ -2598,7 +2661,7 @@ let SuggestTypeLongIdentInModuleOrNamespace depth (modref:ModuleOrNamespaceRef)
25982661
| AccessibleFrom_->
25992662
modref.ModuleOrNamespaceType.AllEntities
26002663
|> Seq.filter(fun e-> IsEntityAccessible amap m ad(modref.NestedTyconRef e))
2601-
|> Seq.map(fun e-> e.DisplayName)
2664+
|> Seq.collect(fun e->[e.DisplayName; e.DemangledModuleOrNamespaceName])
26022665
|> Set.ofSeq
26032666
|_-> Set.empty
26042667

@@ -2628,7 +2691,7 @@ let rec private ResolveTypeLongIdentInModuleOrNamespace (ncenv:NameResolver) (ty
26282691
| AccessibleFrom_->
26292692
modref.ModuleOrNamespaceType.ModulesAndNamespacesByDemangledName
26302693
|> Seq.filter(fun kv-> IsEntityAccessible ncenv.amap m ad(modref.NestedTyconRef kv.Value))
2631-
|> Seq.map(fun e-> e.Value.DisplayName)
2694+
|> Seq.collect(fun e->[e.Value.DisplayName; e.Value.DemangledModuleOrNamespaceName])
26322695
|> Set.ofSeq
26332696
|_-> Set.empty
26342697
raze(UndefinedName(depth,FSComp.SR.undefinedNameNamespaceOrModule,id,suggestPossibleModules))
@@ -2637,7 +2700,13 @@ let rec private ResolveTypeLongIdentInModuleOrNamespace (ncenv:NameResolver) (ty
26372700
lettcrefs= LookupTypeNameInEntityMaybeHaveArity(ncenv.amap, id.idRange, ad, id.idText, TypeNameResolutionStaticArgsInfo.Indefinite, modref)
26382701
match tcrefswith
26392702
|_::_-> tcrefs|> CollectResults(fun tcref-> ResolveTypeLongIdentInTyconRefPrim ncenv typeNameResInfo ad resInfo genOk(depth+1) m tcref rest)
2640-
|[]-> raze(UndefinedName(depth,FSComp.SR.undefinedNameType,id,NoSuggestions))// TODO: suggest ctors
2703+
|[]->
2704+
letsuggestTypes()=
2705+
modref.ModuleOrNamespaceType.TypesByDemangledNameAndArity id.idRange
2706+
|> Seq.map(fun e-> e.Value.DisplayName)
2707+
|> Set.ofSeq
2708+
2709+
raze(UndefinedName(depth,FSComp.SR.undefinedNameType,id,suggestTypes))
26412710
tyconSearch+++ modulSearch
26422711

26432712
/// Resolve a long identifier representing a type
@@ -2676,9 +2745,10 @@ let rec ResolveTypeLongIdentPrim (ncenv:NameResolver) occurence fullyQualified m
26762745
match occurencewith
26772746
| ItemOccurence.UseInAttribute->
26782747
[yield e.Value.DisplayName
2748+
yield e.Value.DemangledModuleOrNamespaceName
26792749
if e.Value.DisplayName.EndsWith"Attribute"then
26802750
yield e.Value.DisplayName.Replace("Attribute","")]
2681-
|_->[e.Value.DisplayName])
2751+
|_->[e.Value.DisplayName; e.Value.DemangledModuleOrNamespaceName])
26822752
|> Set.ofSeq
26832753
|_-> Set.empty
26842754

‎src/fsharp/TypeChecker.fs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4410,8 +4410,9 @@ and TcTyparOrMeasurePar optKind cenv (env:TcEnv) newOk tpenv (Typar(id,_,_) as t
44104410
|> Set.ofSeq
44114411

44124412
Set.union predictions1 predictions2
4413-
4414-
error (UndefinedName(0,FSComp.SR.undefinedNameTypeParameter,id,predictTypeParameters))
4413+
4414+
let reportedId = Ident("'" + id.idText,id.idRange)
4415+
error (UndefinedName(0,FSComp.SR.undefinedNameTypeParameter,reportedId,predictTypeParameters))
44154416

44164417
// OK, this is an implicit declaration of a type parameter
44174418
// The kind defaults to Type

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp