@@ -70,6 +70,7 @@ type internal CompletionContext =
7070// completing records field
7171| RecordFieldof RecordContext
7272| RangeOperator
73+ | NewObjectof pos * HashSet < string >
7374
7475//----------------------------------------------------------------------------
7576// Untyped scope
@@ -387,6 +388,9 @@ type internal UntypedParseInfo(parsed:UntypedParseResults) =
387388 scope.ValidateBreakpointLocationImpl( pos)
388389
389390module internal UntypedParseInfoImpl =
391+
392+ let emptyStringSet = HashSet< string>()
393+
390394let GetUntypedParseResults ( upi : UntypedParseInfo ) = upi.Results
391395
392396let GetRangeOfExprLeftOfDot ( 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
730740let isInRhsOfRangeOp ( p : AstTraversal.TraversePath ) =
731741match 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+ let findSetters argList =
751+ match argListwith
752+ | SynExpr.Paren( SynExpr.Tuple( parameters, _, _), _, _, _) ->
753+ let setters = HashSet()
754+ for pin parametersdo
755+ match pwith
756+ | Setter id-> ignore( setters.Add id.idText)
757+ | _ -> ()
758+ setters
759+ | _ -> emptyStringSet
760+
761+ let endOfLastIdent ( lid : LongIdentWithDots ) =
762+ let last = List.last lid.Lid
763+ last.idRange.End
764+
765+ let endOfClosingTokenOrLastIdent ( mClosing : range option ) ( lid : LongIdentWithDots ) =
766+ match mClosingwith
767+ | Some m-> m.End
768+ | None-> endOfLastIdent lid
769+
770+ let endOfClosingTokenOrIdent ( 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+ let isOnTheRightOfComma ( elements : SynExpr list ) ( commas : range list ) current =
798+ let rec loop 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+
736826let walker =
737827{
738828new AstTraversal.AstVisitorBase<_>() with
@@ -741,7 +831,26 @@ module internal UntypedParseInfoImpl =
741831match 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+ let precedingArgument = 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
746855member this.VisitRecordField ( path , copyOpt , field ) =
747856let contextFromTreePath completionPath =