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

Commit38a0734

Browse files
committed
initial revision of completions for properties in 'new' expressions
1 parent11ede75 commit38a0734

File tree

5 files changed

+373
-204
lines changed

5 files changed

+373
-204
lines changed

‎src/fsharp/nameres.fs‎

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,8 +2452,17 @@ let ResolveRecordOrClassFieldsOfType (ncenv: NameResolver) m ad typ statics =
24522452
|> List.filter(fun rfref-> rfref.IsStatic= statics&& IsFieldInfoAccessible ad rfref)
24532453
|> List.map Item.RecdField
24542454

2455+
[<RequireQualifiedAccess>]
2456+
typeResolveCompletionTargets=
2457+
| Allof(MethInfo->TType->bool)
2458+
| SettablePropertiesAndFields
2459+
memberthis.ResolveAll=
2460+
match thiswith
2461+
| All_->true
2462+
|_->false
2463+
24552464
/// Resolve a (possibly incomplete) long identifier to a set of possible resolutions, qualified by type.
2456-
letResolveCompletionsInType(ncenv:NameResolver)nenvisApplicableMeth m ad statics typ=
2465+
letResolveCompletionsInType(ncenv:NameResolver)nenv(completionTargets:ResolveCompletionTargets)m ad statics typ=
24572466
letg= ncenv.g
24582467
letamap= ncenv.amap
24592468

@@ -2462,21 +2471,23 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
24622471
|> List.filter(fun rfref-> rfref.IsStatic= statics&& IsFieldInfoAccessible ad rfref)
24632472

24642473
letucinfos=
2465-
if statics&& isAppTy g typthen
2474+
ifcompletionTargets.ResolveAll&&statics&& isAppTy g typthen
24662475
lettc,tinst= destAppTy g typ
24672476
tc.UnionCasesAsRefList
24682477
|> List.filter(IsUnionCaseUnseen ad g ncenv.amap m>>not)
24692478
|> List.map(fun ucref-> Item.UnionCase(UnionCaseInfo(tinst,ucref)))
24702479
else[]
24712480

24722481
leteinfos=
2473-
ncenv.InfoReader.GetEventInfosOfType(None,ad,m,typ)
2474-
|> List.filter(fun x->
2475-
IsStandardEventInfo ncenv.InfoReader m ad x&&
2476-
x.IsStatic= statics)
2482+
if completionTargets.ResolveAllthen
2483+
ncenv.InfoReader.GetEventInfosOfType(None,ad,m,typ)
2484+
|> List.filter(fun x->
2485+
IsStandardEventInfo ncenv.InfoReader m ad x&&
2486+
x.IsStatic= statics)
2487+
else[]
24772488

24782489
letnestedTypes=
2479-
if staticsthen
2490+
ifcompletionTargets.ResolveAll&&staticsthen
24802491
typ
24812492
|> GetNestedTypesOfType(ad, ncenv, None, TypeNameResolutionStaticArgsInfo.Indefinite,false, m)
24822493
else
@@ -2494,7 +2505,6 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
24942505
x.IsStatic= statics&&
24952506
IsPropInfoAccessible g amap m ad x)
24962507

2497-
24982508
// Exclude get_ and set_ methods accessed by properties
24992509
letpinfoMethNames=
25002510
(pinfosIncludingUnseen
@@ -2506,13 +2516,15 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25062516
|> List.map(fun pinfo-> pinfo.SetterMethod.LogicalName))
25072517

25082518
leteinfoMethNames=
2509-
[for einfoin einfosdo
2510-
letdelegateType= einfo.GetDelegateType(amap,m)
2511-
let(SigOfFunctionForDelegate(invokeMethInfo,_,_,_))= GetSigOfFunctionForDelegate ncenv.InfoReader delegateType m ad
2512-
// Only events with void return types are suppressed in intellisense.
2513-
if slotSigHasVoidReturnTy(invokeMethInfo.GetSlotSig(amap, m))then
2514-
yield einfo.GetAddMethod().DisplayName
2515-
yield einfo.GetRemoveMethod().DisplayName]
2519+
if completionTargets.ResolveAllthen
2520+
[for einfoin einfosdo
2521+
letdelegateType= einfo.GetDelegateType(amap,m)
2522+
let(SigOfFunctionForDelegate(invokeMethInfo,_,_,_))= GetSigOfFunctionForDelegate ncenv.InfoReader delegateType m ad
2523+
// Only events with void return types are suppressed in intellisense.
2524+
if slotSigHasVoidReturnTy(invokeMethInfo.GetSlotSig(amap, m))then
2525+
yield einfo.GetAddMethod().DisplayName
2526+
yield einfo.GetRemoveMethod().DisplayName]
2527+
else[]
25162528

25172529
letsuppressedMethNames= Zset.ofList String.order(pinfoMethNames@ einfoMethNames)
25182530

@@ -2521,6 +2533,10 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25212533
|> List.filter(fun x->not(PropInfoIsUnseen m x))
25222534

25232535
letminfoFilter(minfo:MethInfo)=
2536+
letisApplicableMeth=
2537+
match completionTargetswith
2538+
| ResolveCompletionTargets.All isApplicableMeth-> isApplicableMeth
2539+
|_-> failwith"internal error: expected completionTargets = ResolveCompletionTargets.All"
25242540
// Only show the Finalize, MemberwiseClose etc. methods on System.Object for values whose static type really is
25252541
// System.Object. Few of these are typically used from F#.
25262542
//
@@ -2559,24 +2575,31 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25592575
result
25602576

25612577
letpinfoItems=
2578+
letpinfos=
2579+
match completionTargetswith
2580+
| ResolveCompletionTargets.SettablePropertiesAndFields-> pinfos|> List.filter(fun p-> p.HasSetter)
2581+
|_-> pinfos
2582+
25622583
pinfos
25632584
|> List.map(fun pinfo-> DecodeFSharpEvent[pinfo] ad g ncenv m)
2564-
|> List.filter(fun pinfo->match pinfowith
2565-
| Some(Item.Event(einfo))-> IsStandardEventInfo ncenv.InfoReader m ad einfo
2566-
|_-> pinfo.IsSome)
2585+
|> List.filter(fun pinfo->
2586+
match pinfowith
2587+
| Some(Item.Event(einfo))-> completionTargets.ResolveAll&& IsStandardEventInfo ncenv.InfoReader m ad einfo
2588+
|_-> pinfo.IsSome)
25672589
|> List.map(fun pinfo->pinfo.Value)
25682590

2569-
letaddersAndRemovers=
2570-
pinfoItems
2571-
|> List.map(function Item.Event(FSEvent(_,_,addValRef,removeValRef))->[addValRef.LogicalName;removeValRef.LogicalName]|_->[])
2572-
|> List.concat
2573-
25742591
// REVIEW: add a name filter here in the common cases?
25752592
letminfos=
2576-
AllMethInfosOfTypeInScope ncenv.InfoReader nenv(None,ad) PreferOverrides m typ
2577-
|> List.filter minfoFilter
2578-
|> List.filter(fun minfo->not(addersAndRemovers|>List.exists(fun ar-> ar= minfo.LogicalName)))
2579-
2593+
if completionTargets.ResolveAllthen
2594+
letaddersAndRemovers=
2595+
pinfoItems
2596+
|> List.map(function Item.Event(FSEvent(_,_,addValRef,removeValRef))->[addValRef.LogicalName;removeValRef.LogicalName]|_->[])
2597+
|> List.concat
2598+
2599+
AllMethInfosOfTypeInScope ncenv.InfoReader nenv(None,ad) PreferOverrides m typ
2600+
|> List.filter minfoFilter
2601+
|> List.filter(fun minfo->not(addersAndRemovers|>List.exists(fun ar-> ar= minfo.LogicalName)))
2602+
else[]
25802603
// Partition methods into overload sets
25812604
let recpartitionl(l:MethInfo list)acc=
25822605
match lwith
@@ -2585,8 +2608,6 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25852608
letnm= h.LogicalName
25862609
partitionl t(NameMultiMap.add nm h acc)
25872610

2588-
2589-
25902611
// Build the results
25912612
ucinfos@
25922613
List.map Item.RecdField rfinfos@
@@ -2884,7 +2905,7 @@ let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionE
28842905

28852906
/// Resolve a (possibly incomplete) long identifier to a set of possible resolutions.
28862907
letResolvePartialLongIdent ncenv nenv isApplicableMeth m ad plid allowObsolete=
2887-
ResolvePartialLongIdentPrim ncenv nenv isApplicableMeth OpenQualified m ad plid allowObsolete
2908+
ResolvePartialLongIdentPrim ncenv nenv(ResolveCompletionTargets.AllisApplicableMeth) OpenQualified m ad plid allowObsolete
28882909

28892910
// REVIEW: has much in common with ResolvePartialLongIdentInModuleOrNamespace - probably they should be united
28902911
let recResolvePartialLongIdentInModuleOrNamespaceForRecordFields(ncenv:NameResolver)nenv m ad(modref:ModuleOrNamespaceRef)plid allowObsolete=

‎src/fsharp/nameres.fsi‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,5 +300,10 @@ val FakeInstantiationGenerator : range -> Typar list -> TType list
300300
/// Resolve a(possibly incomplete) long identifier to a set of possible resolutions.
301301
val ResolvePartialLongIdent: NameResolver-> NameResolutionEnv->(MethInfo-> TType-> bool)-> range-> AccessorDomain-> string list-> bool-> Item list
302302

303+
[<RequireQualifiedAccess>]
304+
type ResolveCompletionTargets=
305+
| Allof(MethInfo->TType->bool)
306+
| SettablePropertiesAndFields
307+
303308
/// Resolve a (possibly incomplete) long identifier to a set of possible resolutions, qualified by type.
304-
val ResolveCompletionsInType: NameResolver-> NameResolutionEnv->(MethInfo-> TType-> bool)-> Range.range-> Infos.AccessorDomain-> bool-> TType-> Item list
309+
valResolveCompletionsInType:NameResolver->NameResolutionEnv->ResolveCompletionTargets->Range.range->Infos.AccessorDomain->bool->TType->Item list

‎src/fsharp/vs/ServiceUntypedParse.fs‎

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ type internal CompletionContext =
7070
// completing records field
7171
| RecordFieldofRecordContext
7272
| RangeOperator
73+
| NewObjectofpos*HashSet<string>
7374

7475
//----------------------------------------------------------------------------
7576
// Untyped scope
@@ -387,6 +388,9 @@ type internal UntypedParseInfo(parsed:UntypedParseResults) =
387388
scope.ValidateBreakpointLocationImpl(pos)
388389

389390
moduleinternalUntypedParseInfoImpl=
391+
392+
letemptyStringSet= HashSet<string>()
393+
390394
letGetUntypedParseResults(upi:UntypedParseInfo)= upi.Results
391395

392396
letGetRangeOfExprLeftOfDot(line,col,parseTreeOpt)=
@@ -726,13 +730,99 @@ module internal UntypedParseInfoImpl =
726730
Some CompletionContext.Invalid
727731
|_-> None
728732

733+
let(|Operator|_|)name e=
734+
match ewith
735+
| SynExpr.App(ExprAtomicFlag.NonAtomic,false, SynExpr.App(ExprAtomicFlag.NonAtomic,true, SynExpr.Ident(ident), lhs,_), rhs,_)
736+
when ident.idText= name-> Some(lhs, rhs)
737+
|_-> None
738+
729739
// checks if we are in rhs of the range operator
730740
letisInRhsOfRangeOp(p:AstTraversal.TraversePath)=
731741
match pwith
732-
| TS.Expr(SynExpr.App(ExprAtomicFlag.NonAtomic,false, SynExpr.App(ExprAtomicFlag.NonAtomic,true, SynExpr.Ident(ident),_,_),_,_))::_
733-
when ident.idText="op_Range"->true
742+
| TS.Expr(Operator"op_Range"_)::_->true
734743
|_->false
735744

745+
let(|Setter|_|)e=
746+
match ewith
747+
| Operator"op_Equality"(SynExpr.Ident id,_)-> Some id
748+
|_-> None
749+
750+
letfindSetters argList=
751+
match argListwith
752+
| SynExpr.Paren(SynExpr.Tuple(parameters,_,_),_,_,_)->
753+
letsetters= HashSet()
754+
for pin parametersdo
755+
match pwith
756+
| Setter id-> ignore(setters.Add id.idText)
757+
|_->()
758+
setters
759+
|_-> emptyStringSet
760+
761+
letendOfLastIdent(lid:LongIdentWithDots)=
762+
letlast= List.last lid.Lid
763+
last.idRange.End
764+
765+
letendOfClosingTokenOrLastIdent(mClosing:range option)(lid:LongIdentWithDots)=
766+
match mClosingwith
767+
| Some m-> m.End
768+
| None-> endOfLastIdent lid
769+
770+
letendOfClosingTokenOrIdent(mClosing:range option)(id:Ident)=
771+
match mClosingwith
772+
| Some m-> m.End
773+
| None-> id.idRange.End
774+
775+
let(|NewObject|_|)e=
776+
match ewith
777+
|(SynExpr.New(_, SynType.LongIdent typeName, arg,_))->
778+
// new A()
779+
Some(endOfLastIdent typeName, findSetters arg)
780+
|(SynExpr.New(_, SynType.App(SynType.LongIdent typeName,_,_,_, mGreaterThan,_,_), arg,_))->
781+
// new A<_>()
782+
Some(endOfClosingTokenOrLastIdent mGreaterThan typeName, findSetters arg)
783+
|(SynExpr.App(ExprAtomicFlag.Atomic,false, SynExpr.Ident id, arg,_))->
784+
// A()
785+
Some(id.idRange.End, findSetters arg)
786+
|(SynExpr.App(ExprAtomicFlag.Atomic,false, SynExpr.TypeApp(SynExpr.Ident id,_,_,_, mGreaterThan,_,_), arg,_))->
787+
// A<_>()
788+
Some(endOfClosingTokenOrIdent mGreaterThan id, findSetters arg)
789+
|(SynExpr.App(ExprAtomicFlag.Atomic,false, SynExpr.LongIdent(_, lid,_,_), arg,_))->
790+
// A.B()
791+
Some(endOfLastIdent lid, findSetters arg)
792+
|(SynExpr.App(ExprAtomicFlag.Atomic,false, SynExpr.TypeApp(SynExpr.LongIdent(_, lid,_,_),_,_,_, mGreaterThan,_,_), arg,_))->
793+
// A.B<_>()
794+
Some(endOfClosingTokenOrLastIdent mGreaterThan lid, findSetters arg)
795+
|_-> None
796+
797+
letisOnTheRightOfComma(elements:SynExpr list)(commas:range list)current=
798+
let recloop elements(commas:range list)=
799+
match elementswith
800+
| x::xs->
801+
match commaswith
802+
| c::cs->
803+
if x=== currentthen posLt c.End pos|| posEq c.End pos
804+
else loop xs cs
805+
|_->false
806+
|_->false
807+
loop elements commas
808+
809+
let(|PartOfParameterList|_|)precedingArgument path=
810+
match pathwith
811+
| TS.Expr(SynExpr.Paren_)::TS.Expr(NewObject(args))::_->
812+
if Option.isSome precedingArgumentthen Noneelse Some args
813+
| TS.Expr(SynExpr.Tuple(elements, commas,_))::TS.Expr(SynExpr.Paren_)::TS.Expr(NewObject(args))::_->
814+
match precedingArgumentwith
815+
| None-> Some args
816+
| Some e->
817+
// if expression is passed then
818+
// 1. find it in among elements of the tuple
819+
// 2. find corresponding comma
820+
// 3. check that current position is past the comma
821+
// this is used for cases like (a = something-here.) if the cursor is after .
822+
// in this case this is not object initializer completion context
823+
if isOnTheRightOfComma elements commas ethen Some argselse None
824+
|_-> None
825+
736826
letwalker=
737827
{
738828
new AstTraversal.AstVisitorBase<_>()with
@@ -741,7 +831,26 @@ module internal UntypedParseInfoImpl =
741831
match defaultTraverse exprwith
742832
| None-> Some(CompletionContext.RangeOperator)// nothing was found - report that we were in the context of range operator
743833
| x-> x// ok, we found something - return it
744-
else defaultTraverse expr
834+
else
835+
match exprwith
836+
// new A($)
837+
| SynExpr.Const(SynConst.Unit, m)when rangeContainsPos m pos->
838+
match pathwith
839+
| TS.Expr(NewObject args)::_-> Some(CompletionContext.NewObject args)
840+
|_-> defaultTraverse expr
841+
// new (... A$)
842+
| SynExpr.Ident idwhen id.idRange.End= pos->
843+
match pathwith
844+
| PartOfParameterList None args-> Some(CompletionContext.NewObject args)
845+
|_-> defaultTraverse expr
846+
// new (A$ = 1)
847+
// new (A = 1,$)
848+
| Setter idwhen id.idRange.End= pos|| rangeBeforePos expr.Range pos->
849+
letprecedingArgument=if id.idRange.End= posthen Noneelse Some expr
850+
match pathwith
851+
| PartOfParameterList precedingArgument args-> Some(CompletionContext.NewObject args)
852+
|_-> defaultTraverse expr
853+
|_-> defaultTraverse expr
745854

746855
memberthis.VisitRecordField(path,copyOpt,field)=
747856
letcontextFromTreePath completionPath=

‎src/fsharp/vs/ServiceUntypedParse.fsi‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ type internal CompletionContext =
6767
// completing records field
6868
| RecordFieldofRecordContext
6969
| RangeOperator
70-
70+
// completing property setters in constructor call
71+
// end of constructor ast node * list of properties that were already set
72+
| NewObjectofpos*HashSet<string>
7173

7274
// implementation details used by other code in the compiler
7375
moduleinternalUntypedParseInfoImpl=

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp