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

Commit1a246cc

Browse files
vladimalatkin
authored andcommitted
Completion in object initializers
fixesdotnet#119closesdotnet#197commitd4dd838Author: Vladimir Matveev <vladima@microsoft.com>Date: Tue Feb 3 16:20:52 2015 -0800 added test for settable extension propertycommit5edc7ccAuthor: Vladimir Matveev <vladima@microsoft.com>Date: Tue Feb 3 16:20:26 2015 -0800 addressed CR feedbackcommitf17c57dAuthor: v2m <desco.by@gmail.com>Date: Sun Feb 1 14:55:02 2015 -0800 added tests for property completion in object creation expressionscommit38a0734Author: v2m <desco.by@gmail.com>Date: Wed Jan 28 11:25:09 2015 -0800 initial revision of completions for properties in 'new' expressions
1 parentea11a9b commit1a246cc

File tree

6 files changed

+467
-206
lines changed

6 files changed

+467
-206
lines changed

‎src/fsharp/nameres.fs‎

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,8 +2459,17 @@ let ResolveRecordOrClassFieldsOfType (ncenv: NameResolver) m ad typ statics =
24592459
|> List.filter(fun rfref-> rfref.IsStatic= statics&& IsFieldInfoAccessible ad rfref)
24602460
|> List.map Item.RecdField
24612461

2462+
[<RequireQualifiedAccess>]
2463+
typeResolveCompletionTargets=
2464+
| Allof(MethInfo->TType->bool)
2465+
| SettablePropertiesAndFields
2466+
memberthis.ResolveAll=
2467+
match thiswith
2468+
| All_->true
2469+
| SettablePropertiesAndFields->false
2470+
24622471
/// Resolve a (possibly incomplete) long identifier to a set of possible resolutions, qualified by type.
2463-
letResolveCompletionsInType(ncenv:NameResolver)nenvisApplicableMeth m ad statics typ=
2472+
letResolveCompletionsInType(ncenv:NameResolver)nenv(completionTargets:ResolveCompletionTargets)m ad statics typ=
24642473
letg= ncenv.g
24652474
letamap= ncenv.amap
24662475

@@ -2469,21 +2478,23 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
24692478
|> List.filter(fun rfref-> rfref.IsStatic= statics&& IsFieldInfoAccessible ad rfref)
24702479

24712480
letucinfos=
2472-
if statics&& isAppTy g typthen
2481+
ifcompletionTargets.ResolveAll&&statics&& isAppTy g typthen
24732482
lettc,tinst= destAppTy g typ
24742483
tc.UnionCasesAsRefList
24752484
|> List.filter(IsUnionCaseUnseen ad g ncenv.amap m>>not)
24762485
|> List.map(fun ucref-> Item.UnionCase(UnionCaseInfo(tinst,ucref),false))
24772486
else[]
24782487

24792488
leteinfos=
2480-
ncenv.InfoReader.GetEventInfosOfType(None,ad,m,typ)
2481-
|> List.filter(fun x->
2482-
IsStandardEventInfo ncenv.InfoReader m ad x&&
2483-
x.IsStatic= statics)
2489+
if completionTargets.ResolveAllthen
2490+
ncenv.InfoReader.GetEventInfosOfType(None,ad,m,typ)
2491+
|> List.filter(fun x->
2492+
IsStandardEventInfo ncenv.InfoReader m ad x&&
2493+
x.IsStatic= statics)
2494+
else[]
24842495

24852496
letnestedTypes=
2486-
if staticsthen
2497+
ifcompletionTargets.ResolveAll&&staticsthen
24872498
typ
24882499
|> GetNestedTypesOfType(ad, ncenv, None, TypeNameResolutionStaticArgsInfo.Indefinite,false, m)
24892500
else
@@ -2501,7 +2512,6 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25012512
x.IsStatic= statics&&
25022513
IsPropInfoAccessible g amap m ad x)
25032514

2504-
25052515
// Exclude get_ and set_ methods accessed by properties
25062516
letpinfoMethNames=
25072517
(pinfosIncludingUnseen
@@ -2513,13 +2523,15 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25132523
|> List.map(fun pinfo-> pinfo.SetterMethod.LogicalName))
25142524

25152525
leteinfoMethNames=
2516-
[for einfoin einfosdo
2517-
letdelegateType= einfo.GetDelegateType(amap,m)
2518-
let(SigOfFunctionForDelegate(invokeMethInfo,_,_,_))= GetSigOfFunctionForDelegate ncenv.InfoReader delegateType m ad
2519-
// Only events with void return types are suppressed in intellisense.
2520-
if slotSigHasVoidReturnTy(invokeMethInfo.GetSlotSig(amap, m))then
2521-
yield einfo.GetAddMethod().DisplayName
2522-
yield einfo.GetRemoveMethod().DisplayName]
2526+
if completionTargets.ResolveAllthen
2527+
[for einfoin einfosdo
2528+
letdelegateType= einfo.GetDelegateType(amap,m)
2529+
let(SigOfFunctionForDelegate(invokeMethInfo,_,_,_))= GetSigOfFunctionForDelegate ncenv.InfoReader delegateType m ad
2530+
// Only events with void return types are suppressed in intellisense.
2531+
if slotSigHasVoidReturnTy(invokeMethInfo.GetSlotSig(amap, m))then
2532+
yield einfo.GetAddMethod().DisplayName
2533+
yield einfo.GetRemoveMethod().DisplayName]
2534+
else[]
25232535

25242536
letsuppressedMethNames= Zset.ofList String.order(pinfoMethNames@ einfoMethNames)
25252537

@@ -2528,6 +2540,10 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25282540
|> List.filter(fun x->not(PropInfoIsUnseen m x))
25292541

25302542
letminfoFilter(minfo:MethInfo)=
2543+
letisApplicableMeth=
2544+
match completionTargetswith
2545+
| ResolveCompletionTargets.All x-> x
2546+
|_-> failwith"internal error: expected completionTargets = ResolveCompletionTargets.All"
25312547
// Only show the Finalize, MemberwiseClose etc. methods on System.Object for values whose static type really is
25322548
// System.Object. Few of these are typically used from F#.
25332549
//
@@ -2566,24 +2582,37 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25662582
result
25672583

25682584
letpinfoItems=
2585+
letpinfos=
2586+
match completionTargetswith
2587+
| ResolveCompletionTargets.SettablePropertiesAndFields-> pinfos|> List.filter(fun p-> p.HasSetter)
2588+
|_-> pinfos
2589+
25692590
pinfos
2570-
|> List.map(fun pinfo-> DecodeFSharpEvent[pinfo] ad g ncenv m)
2571-
|> List.filter(fun pinfo->match pinfowith
2572-
| Some(Item.Event(einfo))-> IsStandardEventInfo ncenv.InfoReader m ad einfo
2573-
|_-> pinfo.IsSome)
2574-
|> List.map(fun pinfo->pinfo.Value)
2575-
2576-
letaddersAndRemovers=
2577-
pinfoItems
2578-
|> List.map(function Item.Event(FSEvent(_,_,addValRef,removeValRef))->[addValRef.LogicalName;removeValRef.LogicalName]|_->[])
2579-
|> List.concat
2580-
2591+
|> List.choose(fun pinfo->
2592+
letpinfoOpt= DecodeFSharpEvent[pinfo] ad g ncenv m
2593+
match pinfoOpt, completionTargetswith
2594+
| Some(Item.Event(einfo)), ResolveCompletionTargets.All_->if IsStandardEventInfo ncenv.InfoReader m ad einfothen pinfoOptelse None
2595+
|_-> pinfoOpt)
2596+
25812597
// REVIEW: add a name filter here in the common cases?
25822598
letminfos=
2583-
AllMethInfosOfTypeInScope ncenv.InfoReader nenv(None,ad) PreferOverrides m typ
2584-
|> List.filter minfoFilter
2585-
|> List.filter(fun minfo->not(addersAndRemovers|>List.exists(fun ar-> ar= minfo.LogicalName)))
2599+
if completionTargets.ResolveAllthen
2600+
letminfos=
2601+
AllMethInfosOfTypeInScope ncenv.InfoReader nenv(None,ad) PreferOverrides m typ
2602+
|> List.filter minfoFilter
2603+
2604+
letaddersAndRemovers=
2605+
pinfoItems
2606+
|> List.map(function Item.Event(FSEvent(_,_,addValRef,removeValRef))->[addValRef.LogicalName;removeValRef.LogicalName]|_->[])
2607+
|> List.concat
2608+
2609+
match addersAndRemoverswith
2610+
|[]-> minfos
2611+
| addersAndRemovers->
2612+
letisNotAdderOrRemover(minfo:MethInfo)=not(addersAndRemovers|> List.exists(fun ar-> ar= minfo.LogicalName))
2613+
List.filter isNotAdderOrRemover minfos
25862614

2615+
else[]
25872616
// Partition methods into overload sets
25882617
let recpartitionl(l:MethInfo list)acc=
25892618
match lwith
@@ -2592,8 +2621,6 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
25922621
letnm= h.LogicalName
25932622
partitionl t(NameMultiMap.add nm h acc)
25942623

2595-
2596-
25972624
// Build the results
25982625
ucinfos@
25992626
List.map Item.RecdField rfinfos@
@@ -2891,7 +2918,7 @@ let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionE
28912918

28922919
/// Resolve a (possibly incomplete) long identifier to a set of possible resolutions.
28932920
letResolvePartialLongIdent ncenv nenv isApplicableMeth m ad plid allowObsolete=
2894-
ResolvePartialLongIdentPrim ncenv nenv isApplicableMeth OpenQualified m ad plid allowObsolete
2921+
ResolvePartialLongIdentPrim ncenv nenv(ResolveCompletionTargets.AllisApplicableMeth) OpenQualified m ad plid allowObsolete
28952922

28962923
// REVIEW: has much in common with ResolvePartialLongIdentInModuleOrNamespace - probably they should be united
28972924
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
@@ -303,5 +303,10 @@ val FakeInstantiationGenerator : range -> Typar list -> TType list
303303
/// Resolve a(possibly incomplete) long identifier to a set of possible resolutions.
304304
val ResolvePartialLongIdent: NameResolver-> NameResolutionEnv->(MethInfo-> TType-> bool)-> range-> AccessorDomain-> string list-> bool-> Item list
305305

306+
[<RequireQualifiedAccess>]
307+
type ResolveCompletionTargets=
308+
| Allof(MethInfo->TType->bool)
309+
| SettablePropertiesAndFields
310+
306311
/// Resolve a (possibly incomplete) long identifier to a set of possible resolutions, qualified by type.
307-
val ResolveCompletionsInType: NameResolver-> NameResolutionEnv->(MethInfo-> TType-> bool)-> Range.range-> Infos.AccessorDomain-> bool-> TType-> Item list
312+
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