diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 60d650ed1fe..e95189ccd41 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -2531,6 +2531,7 @@ let TcMutRecDefns_Phase2 (cenv: cenv) envInitial bindsm scopem mutRecNSInfo (env | SynMemberDefn.LetBindings _ | SynMemberDefn.AutoProperty _ | SynMemberDefn.Member _ + | SynMemberDefn.GetSetMember _ | SynMemberDefn.Open _ -> Some(TyconBindingDefn(containerInfo, newslotsOK, declKind, memb, memb.Range)) @@ -2554,7 +2555,8 @@ let TcMutRecDefns_Phase2 (cenv: cenv) envInitial bindsm scopem mutRecNSInfo (env error(InternalError("Intrinsic augmentations of types are only permitted in the same file as the definition of the type", m)) members |> List.iter (fun mem -> match mem with - | SynMemberDefn.Member _ -> () + | SynMemberDefn.Member _ + | SynMemberDefn.GetSetMember _ | SynMemberDefn.Interface _ -> () | SynMemberDefn.Open _ | SynMemberDefn.AutoProperty _ @@ -4813,10 +4815,12 @@ module TcDeclarations = /// where simpleRepr can contain inherit type, declared fields and virtual slots. /// body = members /// where members contain methods/overrides, also implicit ctor, inheritCall and local definitions. - let rec private SplitTyconDefn (SynTypeDefn(typeInfo=synTyconInfo;typeRepr=trepr; members=extraMembers)) = + let rec private SplitTyconDefn (SynTypeDefn(typeInfo=synTyconInfo;typeRepr=trepr; members=extraMembers)) = + let extraMembers = desugarGetSetMembers extraMembers let implements1 = List.choose (function SynMemberDefn.Interface (interfaceType=ty) -> Some(ty, ty.Range) | _ -> None) extraMembers match trepr with | SynTypeDefnRepr.ObjectModel(kind, cspec, m) -> + let cspec = desugarGetSetMembers cspec CheckMembersForm cspec let fields = cspec |> List.choose (function SynMemberDefn.ValField (f, _) -> Some f | _ -> None) let implements2 = cspec |> List.choose (function SynMemberDefn.Interface (interfaceType=ty) -> Some(ty, ty.Range) | _ -> None) @@ -4833,7 +4837,8 @@ module TcDeclarations = cspec |> List.filter (fun memb -> match memb with | SynMemberDefn.Interface _ - | SynMemberDefn.Member _ + | SynMemberDefn.Member _ + | SynMemberDefn.GetSetMember _ | SynMemberDefn.LetBindings _ | SynMemberDefn.ImplicitCtor _ | SynMemberDefn.AutoProperty _ @@ -4853,7 +4858,7 @@ module TcDeclarations = let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> true | _ -> false) let mLetPortion = synExpr.Range let fldId = ident (CompilerGeneratedName id.idText, mLetPortion) - let headPat = SynPat.LongIdent (SynLongIdent([fldId], [], [None]), None, None, Some noInferredTypars, SynArgPats.Pats [], None, mLetPortion) + let headPat = SynPat.LongIdent (SynLongIdent([fldId], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [], None, mLetPortion) let retInfo = match tyOpt with None -> None | Some ty -> Some (SynReturnInfo((ty, SynInfo.unnamedRetVal), ty.Range)) let isMutable = match propKind with @@ -4881,7 +4886,7 @@ module TcDeclarations = let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> false | _ -> true) let fldId = ident (CompilerGeneratedName id.idText, mMemberPortion) let headPatIds = if isStatic then [id] else [ident ("__", mMemberPortion);id] - let headPat = SynPat.LongIdent (SynLongIdent(headPatIds, [], List.replicate headPatIds.Length None), None, None, Some noInferredTypars, SynArgPats.Pats [], None, mMemberPortion) + let headPat = SynPat.LongIdent (SynLongIdent(headPatIds, [], List.replicate headPatIds.Length None), None, Some noInferredTypars, SynArgPats.Pats [], None, mMemberPortion) match propKind, mGetSetOpt with | SynMemberKind.PropertySet, Some m -> errorR(Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSetNotJustSet(), m)) @@ -4906,7 +4911,7 @@ module TcDeclarations = | SynMemberKind.PropertyGetSet -> let setter = let vId = ident("v", mMemberPortion) - let headPat = SynPat.LongIdent (SynLongIdent(headPatIds, [], List.replicate headPatIds.Length None), None, None, Some noInferredTypars, SynArgPats.Pats [mkSynPatVar None vId], None, mMemberPortion) + let headPat = SynPat.LongIdent (SynLongIdent(headPatIds, [], List.replicate headPatIds.Length None), None, Some noInferredTypars, SynArgPats.Pats [mkSynPatVar None vId], None, mMemberPortion) let rhsExpr = mkSynAssign (SynExpr.Ident fldId) (SynExpr.Ident vId) //let retInfo = match tyOpt with None -> None | Some ty -> Some (SynReturnInfo((ty, SynInfo.unnamedRetVal), ty.Range)) let binding = mkSynBinding (xmlDoc, headPat) (access, false, false, mMemberPortion, DebugPointAtBinding.NoneAtInvisible, None, rhsExpr, rhsExpr.Range, [], [], Some (memberFlags SynMemberKind.PropertySet), SynBindingTrivia.Zero) @@ -5717,7 +5722,8 @@ and TcModuleOrNamespaceElementsMutRec (cenv: cenv) parent typeNames m envInitial let decls = [ MutRecShape.Open (MutRecDataForOpen(target, m, moduleRange, ref [])) ] decls, (openOk, moduleAbbrevOk, attrs) - | SynModuleDecl.Exception (SynExceptionDefn(repr, _, members, _), _m) -> + | SynModuleDecl.Exception (SynExceptionDefn(repr, _, members, _), _m) -> + let members = desugarGetSetMembers members let (SynExceptionDefnRepr(synAttrs, SynUnionCase(ident=SynIdent(id,_)), _repr, xmlDoc, vis, m)) = repr let compInfo = SynComponentInfo(synAttrs, None, [], [id], xmlDoc, false, vis, id.idRange) let decls = [ MutRecShape.Tycon(SynTypeDefn(compInfo, SynTypeDefnRepr.Exception repr, members, None, m, SynTypeDefnTrivia.Zero)) ] diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 525a30d09e2..0de950283e7 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -2636,7 +2636,7 @@ module BindingNormalization = | SynPat.FromParseError(innerPat, _) -> normPattern innerPat - | SynPat.LongIdent (SynLongIdent(longId, _, _), _, toolId, tyargs, SynArgPats.Pats args, vis, m) -> + | SynPat.LongIdent (SynLongIdent(longId, _, _), toolId, tyargs, SynArgPats.Pats args, vis, m) -> let typars = match tyargs with None -> inferredTyparDecls | Some typars -> typars match memberFlagsOpt with | None -> @@ -5710,6 +5710,12 @@ and TcExprUndelayed cenv (overallTy: OverallTy) env tpenv (synExpr: SynExpr) = ) | SynExpr.ObjExpr (synObjTy, argopt, _mWith, binds, members, extraImpls, mNewExpr, m) -> + let members = desugarGetSetMembers members + let extraImpls = + extraImpls + |> List.map (fun (SynInterfaceImpl(interfaceTy, withKeyword, bindings, members, m)) -> + SynInterfaceImpl(interfaceTy, withKeyword, bindings, desugarGetSetMembers members, m) + ) TcNonControlFlowExpr env <| fun env -> let binds = unionBindingAndMembers binds members TcExprObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls, mNewExpr, m) diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index 59a4946c2cb..3959c84da3f 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -885,6 +885,14 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynMemberDefn.AutoProperty (synExpr = synExpr) -> yield! walkExpr true synExpr | SynMemberDefn.ImplicitCtor (_, _, _, _, _, m) -> yield! checkRange m | SynMemberDefn.Member (bind, _) -> yield! walkBind bind + | SynMemberDefn.GetSetMember (getBinding, setBinding, _, _) -> + match getBinding, setBinding with + | None, None -> () + | None, Some binding + | Some binding, None -> yield! walkBind binding + | Some getBinding, Some setBinding -> + yield! walkBind getBinding + yield! walkBind setBinding | SynMemberDefn.Interface(members = Some membs) -> for m in membs do yield! walkMember m diff --git a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs index e54f5922bc9..5458e129ffd 100644 --- a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs +++ b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs @@ -592,9 +592,12 @@ module InterfaceStubGenerator = | InterfaceData.Interface (_, None) -> [] | InterfaceData.Interface (_, Some memberDefns) -> memberDefns - |> Seq.choose (function - | SynMemberDefn.Member (binding, _) -> Some binding - | _ -> None) + |> Seq.collect (function + | SynMemberDefn.Member (binding, _) -> [ binding ] + | SynMemberDefn.GetSetMember (Some getBinding, Some setBinding, _, _) -> [ getBinding; setBinding ] + | SynMemberDefn.GetSetMember (Some binding, None, _, _) + | SynMemberDefn.GetSetMember (None, Some binding, _, _) -> [ binding ] + | _ -> []) |> Seq.choose (|MemberNameAndRange|_|) |> Seq.toList | InterfaceData.ObjExpr (_, bindings) -> List.choose (|MemberNameAndRange|_|) bindings @@ -817,6 +820,12 @@ module InterfaceStubGenerator = else Option.bind (List.tryPick walkSynMemberDefn) members | SynMemberDefn.Member (binding, _range) -> walkBinding binding + | SynMemberDefn.GetSetMember (getBinding, setBinding, _, _) -> + match getBinding, setBinding with + | None, None -> None + | Some binding, None + | None, Some binding -> walkBinding binding + | Some getBinding, Some setBinding -> walkBinding getBinding |> Option.orElseWith (fun () -> walkBinding setBinding) | SynMemberDefn.NestedType (typeDef, _access, _range) -> walkSynTypeDefn typeDef | SynMemberDefn.ValField (_field, _range) -> None | SynMemberDefn.LetBindings (bindings, _isStatic, _isRec, _range) -> List.tryPick walkBinding bindings diff --git a/src/Compiler/Service/ServiceNavigation.fs b/src/Compiler/Service/ServiceNavigation.fs index 61dffe2213c..f162076d44e 100755 --- a/src/Compiler/Service/ServiceNavigation.fs +++ b/src/Compiler/Service/ServiceNavigation.fs @@ -321,44 +321,32 @@ module NavigationImpl = and processMembers members enclosingEntityKind = let members = members - |> List.groupBy (fun x -> x.Range) - |> List.map (fun (range, members) -> - range, - (match members with - | [ memb ] -> - match memb with - | SynMemberDefn.LetBindings (binds, _, _, _) -> List.collect (processBinding false enclosingEntityKind false) binds - | SynMemberDefn.Member (bind, _) -> processBinding true enclosingEntityKind false bind - | SynMemberDefn.ValField (SynField (_, _, Some (rcid), _, _, _, access, range), _) -> - [ - createMember (rcid, NavigationItemKind.Field, FSharpGlyph.Field, range, enclosingEntityKind, false, access) - ] - | SynMemberDefn.AutoProperty (ident = id; accessibility = access) -> - [ - createMember (id, NavigationItemKind.Field, FSharpGlyph.Field, id.idRange, enclosingEntityKind, false, access) - ] - | SynMemberDefn.AbstractSlot (SynValSig (ident = SynIdent (id, _); synType = ty; accessibility = access), _, _) -> - [ - createMember (id, NavigationItemKind.Method, FSharpGlyph.OverridenMethod, ty.Range, enclosingEntityKind, true, access) - ] - | SynMemberDefn.NestedType _ -> failwith "tycon as member????" //processTycon tycon - | SynMemberDefn.Interface(members = Some (membs)) -> processMembers membs enclosingEntityKind |> snd - | _ -> [] - // can happen if one is a getter and one is a setter - | [ SynMemberDefn.Member(memberDefn = SynBinding(headPat = SynPat.LongIdent (longDotId = lid1; extraId = Some (info1))) as binding1) - SynMemberDefn.Member(memberDefn = SynBinding(headPat = SynPat.LongIdent (longDotId = lid2; extraId = Some (info2))) as binding2) ] -> - // ensure same long id - assert - ((lid1.LongIdent, lid2.LongIdent) - ||> List.forall2 (fun x y -> x.idText = y.idText)) - // ensure one is getter, other is setter - assert - ((info1.idText = "set" && info2.idText = "get") - || (info2.idText = "set" && info1.idText = "get")) - // both binding1 and binding2 have same range, so just try the first one, else try the second one - match processBinding true enclosingEntityKind false binding1 with - | [] -> processBinding true enclosingEntityKind false binding2 - | x -> x + |> List.map (fun md -> + md.Range, + (match md with + | SynMemberDefn.LetBindings (binds, _, _, _) -> List.collect (processBinding false enclosingEntityKind false) binds + | SynMemberDefn.GetSetMember (Some bind, None, _, _) + | SynMemberDefn.GetSetMember (None, Some bind, _, _) + | SynMemberDefn.Member (bind, _) -> processBinding true enclosingEntityKind false bind + | SynMemberDefn.ValField (SynField (_, _, Some (rcid), _, _, _, access, range), _) -> + [ + createMember (rcid, NavigationItemKind.Field, FSharpGlyph.Field, range, enclosingEntityKind, false, access) + ] + | SynMemberDefn.AutoProperty (ident = id; accessibility = access) -> + [ + createMember (id, NavigationItemKind.Field, FSharpGlyph.Field, id.idRange, enclosingEntityKind, false, access) + ] + | SynMemberDefn.AbstractSlot (SynValSig (ident = SynIdent (id, _); synType = ty; accessibility = access), _, _) -> + [ + createMember (id, NavigationItemKind.Method, FSharpGlyph.OverridenMethod, ty.Range, enclosingEntityKind, true, access) + ] + | SynMemberDefn.NestedType _ -> failwith "tycon as member????" //processTycon tycon + | SynMemberDefn.Interface(members = Some (membs)) -> processMembers membs enclosingEntityKind |> snd + | SynMemberDefn.GetSetMember (Some getBinding, Some setBinding, _, _) -> + [ + yield! processBinding true enclosingEntityKind false getBinding + yield! processBinding true enclosingEntityKind false setBinding + ] | _ -> [])) let m2 = members |> Seq.map fst |> Seq.fold unionRangesChecked range.Zero @@ -997,6 +985,9 @@ module NavigateTo = walkSynMemberDefn m container | None -> () | SynMemberDefn.Member (binding, _) -> addBinding binding None container + | SynMemberDefn.GetSetMember (getBinding, setBinding, _, _) -> + Option.iter (fun b -> addBinding b None container) getBinding + Option.iter (fun b -> addBinding b None container) setBinding | SynMemberDefn.NestedType (typeDef, _, _) -> walkSynTypeDefn typeDef container | SynMemberDefn.ValField (field, _) -> addField field false container | SynMemberDefn.LetBindings (bindings, _, _, _) -> diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index b45b34658cf..32e20db6486 100755 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -824,47 +824,19 @@ module SyntaxTraversal = and normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path traverseInherit (synMemberDefns: SynMemberDefns) = synMemberDefns // property getters are setters are two members that can have the same range, so do some somersaults to deal with this - |> Seq.groupBy (fun x -> x.Range) - |> Seq.choose (fun (r, mems) -> - match mems |> Seq.toList with - | [ mem ] -> // the typical case, a single member has this range 'r' - Some(dive mem r (traverseSynMemberDefn path traverseInherit)) - | [ SynMemberDefn.Member(memberDefn = SynBinding(headPat = SynPat.LongIdent (longDotId = lid1; extraId = Some (info1)))) as mem1 - SynMemberDefn.Member(memberDefn = SynBinding(headPat = SynPat.LongIdent (longDotId = lid2; extraId = Some (info2)))) as mem2 ] -> // can happen if one is a getter and one is a setter - // ensure same long id - assert - ((lid1.LongIdent, lid2.LongIdent) - ||> List.forall2 (fun x y -> x.idText = y.idText)) - // ensure one is getter, other is setter - assert - ((info1.idText = "set" && info2.idText = "get") - || (info2.idText = "set" && info1.idText = "get")) - - Some( - r, - (fun () -> - // both mem1 and mem2 have same range, would violate dive-and-pick assertions, so just try the first one, else try the second one: - match traverseSynMemberDefn path (fun _ -> None) mem1 with - | Some _ as x -> x - | _ -> traverseSynMemberDefn path (fun _ -> None) mem2) - ) - | [] -> -#if DEBUG - assert false - failwith "impossible, Seq.groupBy never returns empty results" -#else - // swallow AST error and recover silently - None -#endif - | _ -> -#if DEBUG - assert false // more than 2 members claim to have the same range, this indicates a bug in the AST - failwith "bug in AST" -#else - // swallow AST error and recover silently - None -#endif - ) + |> Seq.map (fun mb -> + match mb with + | SynMemberDefn.GetSetMember (Some binding, None, m, _) + | SynMemberDefn.GetSetMember (None, Some binding, m, _) -> + dive (SynMemberDefn.Member(binding, m)) m (traverseSynMemberDefn path traverseInherit) + | SynMemberDefn.GetSetMember (Some getBinding, Some setBinding, m, _) -> + let traverse () = + match traverseSynMemberDefn path (fun _ -> None) (SynMemberDefn.Member(getBinding, m)) with + | Some _ as x -> x + | None -> traverseSynMemberDefn path (fun _ -> None) (SynMemberDefn.Member(setBinding, m)) + + m, traverse + | mem -> dive mem mem.Range (traverseSynMemberDefn path traverseInherit)) and traverseSynTypeDefn origPath (SynTypeDefn (synComponentInfo, synTypeDefnRepr, synMemberDefns, _, tRange, _) as tydef) = let path = SyntaxNode.SynTypeDefn tydef :: origPath @@ -910,6 +882,15 @@ module SyntaxTraversal = match m with | SynMemberDefn.Open (_longIdent, _range) -> None | SynMemberDefn.Member (synBinding, _range) -> traverseSynBinding path synBinding + | SynMemberDefn.GetSetMember (getBinding, setBinding, _, _) -> + match getBinding, setBinding with + | None, None -> None + | Some binding, None + | None, Some binding -> traverseSynBinding path binding + | Some getBinding, Some setBinding -> + traverseSynBinding path getBinding + |> Option.orElseWith (fun () -> traverseSynBinding path setBinding) + | SynMemberDefn.ImplicitCtor (_synAccessOption, _synAttributes, simplePats, _identOption, _doc, _range) -> match simplePats with | SynSimplePats.SimplePats (simplePats, _) -> visitor.VisitSimplePats(path, simplePats) diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index febfa3128f9..f61893d0eaf 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -875,6 +875,13 @@ module ParsedInput = | SynMemberDefn.Member (binding, _) -> walkBinding binding + | SynMemberDefn.GetSetMember (getBinding, setBinding, _, _) -> + match getBinding, setBinding with + | None, None -> None + | Some binding, None + | None, Some binding -> walkBinding binding + | Some getBinding, Some setBinding -> walkBinding getBinding |> Option.orElseWith (fun () -> walkBinding setBinding) + | SynMemberDefn.ImplicitCtor (_, Attributes attrs, SynSimplePats.SimplePats (simplePats, _), _, _, _) -> List.tryPick walkAttribute attrs |> Option.orElseWith (fun () -> List.tryPick walkSimplePat simplePats) @@ -1860,6 +1867,9 @@ module ParsedInput = match memb with | SynMemberDefn.AbstractSlot (valSig, _, _) -> walkValSig valSig | SynMemberDefn.Member (binding, _) -> walkBinding binding + | SynMemberDefn.GetSetMember (getBinding, setBinding, _, _) -> + Option.iter walkBinding getBinding + Option.iter walkBinding setBinding | SynMemberDefn.ImplicitCtor (_, Attributes attrs, SynSimplePats.SimplePats (simplePats, _), _, _, _) -> List.iter walkAttribute attrs List.iter walkSimplePat simplePats diff --git a/src/Compiler/Service/ServiceStructure.fs b/src/Compiler/Service/ServiceStructure.fs index 4e27fda1bc7..8e3a96112ca 100644 --- a/src/Compiler/Service/ServiceStructure.fs +++ b/src/Compiler/Service/ServiceStructure.fs @@ -587,6 +587,15 @@ module Structure = parseAttributes attrs parseBinding binding + | SynMemberDefn.GetSetMember (getBinding, setBinding, m, _) -> + getBinding + |> Option.map (fun b -> SynMemberDefn.Member(b, m)) + |> Option.iter (parseSynMemberDefn objectModelRange) + + setBinding + |> Option.map (fun b -> SynMemberDefn.Member(b, m)) + |> Option.iter (parseSynMemberDefn objectModelRange) + | SynMemberDefn.LetBindings (bindings, _, _, _) -> parseBindings bindings | SynMemberDefn.Interface (interfaceType = tp; members = iMembers; range = r) -> diff --git a/src/Compiler/Service/ServiceXmlDocParser.fs b/src/Compiler/Service/ServiceXmlDocParser.fs index dac61838746..f0b137b4bb8 100644 --- a/src/Compiler/Service/ServiceXmlDocParser.fs +++ b/src/Compiler/Service/ServiceXmlDocParser.fs @@ -161,6 +161,19 @@ module XmlDocParsing = let paramNames = digNamesFrom synPat XmlDocable(line, indent, paramNames) + | SynMemberDefn.GetSetMember (getBinding, setBinding, m, _) -> + yield! + getBinding + |> Option.map (fun b -> SynMemberDefn.Member(b, m)) + |> Option.toList + |> List.collect getXmlDocablesSynMemberDefn + + yield! + setBinding + |> Option.map (fun b -> SynMemberDefn.Member(b, m)) + |> Option.toList + |> List.collect getXmlDocablesSynMemberDefn + | SynMemberDefn.AbstractSlot (valSig, _, range) -> let (SynValSig (attributes = synAttributes; arity = synValInfo; xmlDoc = preXmlDoc)) = valSig diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index bf25d2790c6..54a31687eb5 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -411,6 +411,12 @@ let raiseParseErrorAt m s = // This initiates error recovery raise RecoverableParseError +let (|GetIdent|SetIdent|OtherIdent|) (ident: Ident option) = + match ident with + | Some ident when ident.idText = "get" -> GetIdent ident.idRange + | Some ident when ident.idText = "set" -> SetIdent ident.idRange + | _ -> OtherIdent + let mkSynMemberDefnGetSet (parseState: IParseState) (opt_inline: bool) @@ -432,9 +438,15 @@ let mkSynMemberDefnGetSet let xmlDoc = grabXmlDocAtRangeStart (parseState, attrs, rangeStart) let tryMkSynMemberDefnMember - (withPropertyKeyword: PropertyKeyword option) - (optInline, optAttrs: SynAttributeList list, (bindingPat, mBindLhs), optReturnType, mEquals, expr, mExpr) - = + ( + optInline, + optAttrs: SynAttributeList list, + (bindingPat, mBindLhs), + optReturnType, + mEquals, + expr, + mExpr + ) : (SynMemberDefn * Ident option) option = let optInline = opt_inline || optInline // optional attributes are only applied to getters and setters // the "top level" attrs will be applied to both @@ -611,7 +623,7 @@ let mkSynMemberDefnGetSet // This uses the 'this' variable from the first and the patterns for the get/set binding, // replacing the get/set identifier. A little gross. - let bindingPatAdjusted, xmlDocAdjusted = + let (bindingPatAdjusted, getOrSetIdentOpt), xmlDocAdjusted = let trivia: SynBindingTrivia = { @@ -640,7 +652,7 @@ let mkSynMemberDefnGetSet let lidOuter, lidVisOuter = match bindingPatOuter with - | SynPat.LongIdent (lid, _, None, None, SynArgPats.Pats [], lidVisOuter, _m) -> lid, lidVisOuter + | SynPat.LongIdent (lid, _, None, SynArgPats.Pats [], lidVisOuter, _m) -> lid, lidVisOuter | SynPat.Named (SynIdent (id, _), _, visOuter, _m) | SynPat.As (_, SynPat.Named (SynIdent (id, _), _, visOuter, _m), _) -> SynLongIdent([ id ], [], [ None ]), visOuter | _ -> raiseParseErrorAt mWholeBindLhs (FSComp.SR.parsInvalidDeclarationSyntax ()) @@ -680,21 +692,17 @@ let mkSynMemberDefnGetSet else args - SynPat.LongIdent( - lidOuter, - withPropertyKeyword, - Some(id), - tyargs, - SynArgPats.Pats args, - mergeLidVisOuter lidVisInner, - m - ) + SynPat.LongIdent(lidOuter, Some id, tyargs, SynArgPats.Pats args, mergeLidVisOuter lidVisInner, m), Some id | SynPat.Named (_, _, lidVisInner, m) | SynPat.As (_, SynPat.Named (_, _, lidVisInner, m), _) -> - SynPat.LongIdent(lidOuter, None, None, None, SynArgPats.Pats [], mergeLidVisOuter lidVisInner, m) - | SynPat.Typed (p, ty, m) -> SynPat.Typed(go p, ty, m) - | SynPat.Attrib (p, attribs, m) -> SynPat.Attrib(go p, attribs, m) - | SynPat.Wild m -> SynPat.Wild(m) + SynPat.LongIdent(lidOuter, None, None, SynArgPats.Pats [], mergeLidVisOuter lidVisInner, m), None + | SynPat.Typed (p, ty, m) -> + let p, id = go p + SynPat.Typed(p, ty, m), id + | SynPat.Attrib (p, attribs, m) -> + let p, id = go p + SynPat.Attrib(p, attribs, m), id + | SynPat.Wild m -> SynPat.Wild(m), None | _ -> raiseParseErrorAt mWholeBindLhs (FSComp.SR.parsInvalidDeclarationSyntax ()) go pv, PreXmlDoc.Merge doc2 doc @@ -719,16 +727,112 @@ let mkSynMemberDefnGetSet let memberRange = unionRanges rangeStart mWhole |> unionRangeWithXmlDoc xmlDocAdjusted - Some(SynMemberDefn.Member(binding, memberRange)) + Some(SynMemberDefn.Member(binding, memberRange), getOrSetIdentOpt) // Iterate over 1 or 2 'get'/'set' entries match classDefnMemberGetSetElements with - | [ h ] -> List.choose id [ tryMkSynMemberDefnMember (Some(PropertyKeyword.With mWith)) h ] + | [ h ] -> + match tryMkSynMemberDefnMember h with + | Some (memberDefn, getSetIdentOpt) -> + match memberDefn, getSetIdentOpt with + | SynMemberDefn.Member _, None -> [ memberDefn ] + | SynMemberDefn.Member (binding, m), Some getOrSet -> + if getOrSet.idText = "get" then + let trivia = + { + WithKeyword = mWith + GetKeyword = Some getOrSet.idRange + AndKeyword = None + SetKeyword = None + } + + [ SynMemberDefn.GetSetMember(Some binding, None, m, trivia) ] + else + let trivia = + { + WithKeyword = mWith + GetKeyword = None + AndKeyword = None + SetKeyword = Some getOrSet.idRange + } + + [ SynMemberDefn.GetSetMember(None, Some binding, m, trivia) ] + | _ -> [] + | None -> [] | [ g; s ] -> - List.choose - id - [ - tryMkSynMemberDefnMember (Some(PropertyKeyword.With mWith)) g - tryMkSynMemberDefnMember (Option.map PropertyKeyword.And mAnd) s - ] + let getter = tryMkSynMemberDefnMember g + let setter = tryMkSynMemberDefnMember s + + match getter, setter with + | Some (SynMemberDefn.Member (getBinding, mGet), getIdent), Some (SynMemberDefn.Member (setBinding, mSet), setIdent) -> + let range = unionRanges mGet mSet + + let trivia = + match getIdent, setIdent with + | GetIdent mGet, SetIdent mSet + | SetIdent mSet, GetIdent mGet -> + { + WithKeyword = mWith + GetKeyword = Some mGet + AndKeyword = mAnd + SetKeyword = Some mSet + } + | OtherIdent, GetIdent mGet + | GetIdent mGet, OtherIdent -> + { + WithKeyword = mWith + GetKeyword = Some mGet + AndKeyword = mAnd + SetKeyword = None + } + | OtherIdent, SetIdent mSet + | SetIdent mSet, OtherIdent -> + { + WithKeyword = mWith + GetKeyword = None + AndKeyword = mAnd + SetKeyword = Some mSet + } + | _ -> + { + WithKeyword = mWith + AndKeyword = mAnd + GetKeyword = None + SetKeyword = None + } + + [ SynMemberDefn.GetSetMember(Some getBinding, Some setBinding, range, trivia) ] + | Some (SynMemberDefn.Member (binding, m), getOrSet), None + | None, Some (SynMemberDefn.Member (binding, m), getOrSet) -> + let trivia = + match getOrSet with + | GetIdent mGet -> + { + WithKeyword = mWith + GetKeyword = Some mGet + AndKeyword = mAnd + SetKeyword = None + } + | SetIdent mSet -> + { + WithKeyword = mWith + GetKeyword = None + AndKeyword = mAnd + SetKeyword = Some mSet + } + | OtherIdent -> + { + WithKeyword = mWith + AndKeyword = mAnd + GetKeyword = None + SetKeyword = None + } + + if trivia.GetKeyword.IsSome then + [ SynMemberDefn.GetSetMember(Some binding, None, m, trivia) ] + elif trivia.SetKeyword.IsSome then + [ SynMemberDefn.GetSetMember(None, Some binding, m, trivia) ] + else + [] + | _ -> [] | _ -> [] diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 4a44fdb7c29..9bcc3a8efe8 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -478,7 +478,7 @@ type SynExpr = argOptions: (SynExpr * Ident option) option * withKeyword: range option * bindings: SynBinding list * - members: SynMemberDefn list * + members: SynMemberDefns * extraImpls: SynInterfaceImpl list * newExprRange: range * range: range @@ -889,7 +889,6 @@ type SynPat = | LongIdent of longDotId: SynLongIdent * - propertyKeyword: PropertyKeyword option * extraId: Ident option * // holds additional ident for tooling typarDecls: SynValTyparDecls option * // usually None: temporary used to parse "f<'a> x = x" argPats: SynArgPats * @@ -946,18 +945,13 @@ type SynPat = | SynPat.Paren (range = m) | SynPat.FromParseError (range = m) -> m -[] -type PropertyKeyword = - | With of range - | And of range - [] type SynInterfaceImpl = | SynInterfaceImpl of interfaceTy: SynType * withKeyword: range option * bindings: SynBinding list * - members: SynMemberDefn list * + members: SynMemberDefns * range: range [] @@ -1373,6 +1367,12 @@ type SynMemberDefn = | Member of memberDefn: SynBinding * range: range + | GetSetMember of + memberDefnForGet: SynBinding option * + memberDefnForSet: SynBinding option * + range: range * + trivia: SynMemberGetSetTrivia + | ImplicitCtor of accessibility: SynAccess option * attributes: SynAttributes * @@ -1413,6 +1413,7 @@ type SynMemberDefn = member d.Range = match d with | SynMemberDefn.Member (range = m) + | SynMemberDefn.GetSetMember (range = m) | SynMemberDefn.Interface (range = m) | SynMemberDefn.Open (range = m) | SynMemberDefn.LetBindings (range = m) diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 0bc4d3e978d..357823b658e 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -565,7 +565,7 @@ type SynExpr = argOptions: (SynExpr * Ident option) option * withKeyword: range option * bindings: SynBinding list * - members: SynMemberDefn list * + members: SynMemberDefns * extraImpls: SynInterfaceImpl list * newExprRange: range * range: range @@ -1041,7 +1041,6 @@ type SynPat = /// A long identifier pattern possibly with argument patterns | LongIdent of longDotId: SynLongIdent * - propertyKeyword: PropertyKeyword option * extraId: Ident option * // holds additional ident for tooling typarDecls: SynValTyparDecls option * // usually None: temporary used to parse "f<'a> x = x" argPats: SynArgPats * @@ -1089,12 +1088,6 @@ type SynPat = /// Gets the syntax range of this construct member Range: range -/// Represents a used keyword for a property member -[] -type PropertyKeyword = - | With of range - | And of range - /// Represents a set of bindings that implement an interface [] type SynInterfaceImpl = @@ -1102,7 +1095,7 @@ type SynInterfaceImpl = interfaceTy: SynType * withKeyword: range option * bindings: SynBinding list * - members: SynMemberDefn list * + members: SynMemberDefns * range: range /// Represents a clause in a 'match' expression @@ -1556,6 +1549,13 @@ type SynMemberDefn = /// A 'member' definition within a type | Member of memberDefn: SynBinding * range: range + /// A 'member' definition with get/set accessors within a type + | GetSetMember of + memberDefnForGet: SynBinding option * + memberDefnForSet: SynBinding option * + range: range * + trivia: SynMemberGetSetTrivia + /// An implicit constructor definition | ImplicitCtor of accessibility: SynAccess option * diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs index af767c5ac6d..546a1b1ade7 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs @@ -184,7 +184,7 @@ let mkSynThisPatVar (id: Ident) = SynPat.Named(SynIdent(id, None), true, None, id.idRange) let mkSynPatMaybeVar lidwd vis m = - SynPat.LongIdent(lidwd, None, None, None, SynArgPats.Pats [], vis, m) + SynPat.LongIdent(lidwd, None, None, SynArgPats.Pats [], vis, m) /// Extract the argument for patterns corresponding to the declaration of 'new ... = ...' let (|SynPatForConstructorDecl|_|) x = @@ -994,3 +994,26 @@ let rec normalizeTupleExpr exprs commas : SynExpr list * range list = innerExprs @ rest, innerCommas @ commas | _ -> exprs, commas + +/// Remove all members that were captures as SynMemberDefn.GetSetMember +let rec desugarGetSetMembers (memberDefns: SynMemberDefns) = + memberDefns + |> List.collect (fun md -> + match md with + | SynMemberDefn.GetSetMember (Some (SynBinding _ as getBinding), + Some (SynBinding _ as setBinding), + m, + { + GetKeyword = Some mGet + SetKeyword = Some mSet + }) -> + if Position.posLt mGet.Start mSet.Start then + [ SynMemberDefn.Member(getBinding, m); SynMemberDefn.Member(setBinding, m) ] + else + [ SynMemberDefn.Member(setBinding, m); SynMemberDefn.Member(getBinding, m) ] + | SynMemberDefn.GetSetMember (Some binding, None, m, _) + | SynMemberDefn.GetSetMember (None, Some binding, m, _) -> [ SynMemberDefn.Member(binding, m) ] + | SynMemberDefn.Interface (interfaceType, withKeyword, members, m) -> + let members = Option.map desugarGetSetMembers members + [ SynMemberDefn.Interface(interfaceType, withKeyword, members, m) ] + | md -> [ md ]) diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi b/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi index 30035546550..edda8d21d5b 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi @@ -342,3 +342,5 @@ val prependIdentInLongIdentWithTrivia: ident: SynIdent -> dotm: range -> lid: Sy val mkDynamicArgExpr: expr: SynExpr -> SynExpr val normalizeTupleExpr: exprs: SynExpr list -> commas: range list -> SynExpr list * range List + +val desugarGetSetMembers: memberDefns: SynMemberDefns -> SynMemberDefns diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs index 86bad54c2ca..679ec9156a7 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs @@ -233,3 +233,12 @@ type SynValSigTrivia = [] type SynTypeFunTrivia = { ArrowRange: range } + +[] +type SynMemberGetSetTrivia = + { + WithKeyword: range + GetKeyword: range option + AndKeyword: range option + SetKeyword: range option + } diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi index 5339bd1dd35..4490e0ec57c 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi @@ -332,3 +332,20 @@ type SynTypeFunTrivia = /// The syntax range of the `->` token. ArrowRange: range } + +/// Represents additional information for SynMemberDefn.GetSetMember +[] +type SynMemberGetSetTrivia = + { + /// The syntax range of the `with` keyword + WithKeyword: range + + /// The syntax range of the `get` keyword + GetKeyword: range option + + /// The syntax range of the `and` keyword + AndKeyword: range option + + /// The syntax range of the `set` keyword + SetKeyword: range option + } diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 111765fbbba..ae048f25464 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -1950,7 +1950,7 @@ classDefnMember: let expr = $7 let valSynData = SynValData (Some (CtorMemberFlags SynMemberFlagsTrivia.Zero), SynValInfo([SynInfo.InferSynArgInfoFromPat $4], SynInfo.unnamedRetVal), $5) let vis = $2 - let declPat = SynPat.LongIdent (SynLongIdent([mkSynId (rhs parseState 3) "new"], [], [None]), None, None, Some noInferredTypars, SynArgPats.Pats [$4], vis, rhs parseState 3) + let declPat = SynPat.LongIdent (SynLongIdent([mkSynId (rhs parseState 3) "new"], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [$4], vis, rhs parseState 3) // Check that 'SynPatForConstructorDecl' matches this correctly assert (match declPat with SynPatForConstructorDecl _ -> true | _ -> false) let synBindingTrivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals } @@ -2716,7 +2716,7 @@ cPrototype: SynExpr.Const (SynConst.String("extern was not given a DllImport attribute", SynStringKind.Regular, rhs parseState 8), rhs parseState 8), mRhs) (fun attrs _ -> - let bindingPat = SynPat.LongIdent (SynLongIdent([nm], [], [None]), None, None, Some noInferredTypars, SynArgPats.Pats [SynPat.Tuple(false, args, argsm)], vis, nmm) + let bindingPat = SynPat.LongIdent (SynLongIdent([nm], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [SynPat.Tuple(false, args, argsm)], vis, nmm) let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let xmlDoc = grabXmlDoc(parseState, attrs, 1) let binding = @@ -3088,7 +3088,7 @@ headBindingPattern: SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) } | headBindingPattern COLON_COLON headBindingPattern - { SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, None, SynArgPats.Pats [SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3)], None, lhs parseState) } + { SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, SynArgPats.Pats [SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3)], None, lhs parseState) } | tuplePatternElements %prec pat_tuple { SynPat.Tuple(false, List.rev $1, lhs parseState) } @@ -3128,43 +3128,43 @@ namePatPair: constrPattern: | atomicPatternLongIdent explicitValTyparDecls { let vis, lid = $1 - SynPat.LongIdent (lid, None, None, Some $2, SynArgPats.Pats [], vis, lhs parseState) } + SynPat.LongIdent (lid, None, Some $2, SynArgPats.Pats [], vis, lhs parseState) } | atomicPatternLongIdent explicitValTyparDecls atomicPatsOrNamePatPairs %prec pat_app { let vis, lid = $1 let args, argsM = $3 let m = unionRanges (rhs2 parseState 1 2) argsM - SynPat.LongIdent (lid, None, None, Some $2, args, vis, m) } + SynPat.LongIdent (lid, None, Some $2, args, vis, m) } | atomicPatternLongIdent explicitValTyparDecls HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $4 let m = unionRanges (rhs2 parseState 1 2) argsM - SynPat.LongIdent (lid, None, None, Some $2, args, vis, m) } + SynPat.LongIdent (lid, None, Some $2, args, vis, m) } | atomicPatternLongIdent explicitValTyparDecls HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $4 let m = unionRanges (rhs2 parseState 1 2) argsM - SynPat.LongIdent (lid, None, None, Some $2, args, vis, m) } + SynPat.LongIdent (lid, None, Some $2, args, vis, m) } | atomicPatternLongIdent atomicPatsOrNamePatPairs %prec pat_app { let vis, lid = $1 let args, argsM = $2 let m = unionRanges (rhs parseState 1) argsM - SynPat.LongIdent (lid, None, None, None, args, vis, m) } + SynPat.LongIdent (lid, None, None, args, vis, m) } | atomicPatternLongIdent HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $3 let m = unionRanges (rhs parseState 1) argsM - SynPat.LongIdent (lid, None, None, None, args, vis, m) } + SynPat.LongIdent (lid, None, None, args, vis, m) } | atomicPatternLongIdent HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $3 let m = unionRanges (rhs parseState 1) argsM - SynPat.LongIdent (lid, None, None, None, args, vis, m) } + SynPat.LongIdent (lid, None, None, args, vis, m) } | COLON_QMARK atomTypeOrAnonRecdType %prec pat_isinst { SynPat.IsInst($2, lhs parseState) } @@ -3330,7 +3330,7 @@ parenPattern: SynPat.Attrib($2, $1, lhsm) } | parenPattern COLON_COLON parenPattern - { SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, None, SynArgPats.Pats [ SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3) ], None, lhs parseState) } + { SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, SynArgPats.Pats [ SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3) ], None, lhs parseState) } | constrPattern { $1 } @@ -4862,7 +4862,7 @@ objExprBindings: let memberDefns = $2 |> (List.choose (function - | SynMemberDefn.Member _ as memberDefn -> Some memberDefn + | (SynMemberDefn.Member _ | SynMemberDefn.GetSetMember _ ) as memberDefn -> Some memberDefn | SynMemberDefn.AutoProperty(range = m) -> errorR(Error(FSComp.SR.parsIllegalMemberVarInObjectImplementation(), m)); None | x -> errorR(Error(FSComp.SR.parsMemberIllegalInObjectImplementation(), x.Range)); None)) mWithKwd, [], memberDefns } diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/ClassTypes/GetSetMembers/GetSetMembers.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/ClassTypes/GetSetMembers/GetSetMembers.fs new file mode 100644 index 00000000000..5c2d6dcc441 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/ClassTypes/GetSetMembers/GetSetMembers.fs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.ComponentTests.Conformance.ClassTypes + +open Xunit +open FSharp.Test.Compiler + +module GetSetMembers = + + [] + let WithGetAndSet() = + Fsx """ +type Foo() = + let mutable bar = "" + + member this.Bar + with get () = bar + and set nextBar = bar <- nextBar + """ + |> withLangVersion50 + |> typecheck + |> shouldSucceed + |> ignore + + [] + let WithGet() = + Fsx """ +type Foo() = + let mutable bar = "" + + member this.Bar + with get () = bar + """ + |> withLangVersion50 + |> typecheck + |> shouldSucceed + |> ignore + + [] + let WithSet() = + Fsx """ +type Foo() = + let mutable bar = "" + + member this.Bar + with set nextBar = bar <- nextBar + """ + |> withLangVersion50 + |> typecheck + |> shouldSucceed + |> ignore \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 562fbb40a88..cf7ae11db7b 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -32,7 +32,8 @@ - + + diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 9343710b77a..090d64e02c7 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -5704,25 +5704,6 @@ FSharp.Compiler.Syntax.PrettyNaming: System.String FormatAndOtherOverloadsString FSharp.Compiler.Syntax.PrettyNaming: System.String FsiDynamicModulePrefix FSharp.Compiler.Syntax.PrettyNaming: System.String NormalizeIdentifierBackticks(System.String) FSharp.Compiler.Syntax.PrettyNaming: System.String get_FsiDynamicModulePrefix() -FSharp.Compiler.Syntax.PropertyKeyword -FSharp.Compiler.Syntax.PropertyKeyword+And: FSharp.Compiler.Text.Range Item -FSharp.Compiler.Syntax.PropertyKeyword+And: FSharp.Compiler.Text.Range get_Item() -FSharp.Compiler.Syntax.PropertyKeyword+Tags: Int32 And -FSharp.Compiler.Syntax.PropertyKeyword+Tags: Int32 With -FSharp.Compiler.Syntax.PropertyKeyword+With: FSharp.Compiler.Text.Range Item -FSharp.Compiler.Syntax.PropertyKeyword+With: FSharp.Compiler.Text.Range get_Item() -FSharp.Compiler.Syntax.PropertyKeyword: Boolean IsAnd -FSharp.Compiler.Syntax.PropertyKeyword: Boolean IsWith -FSharp.Compiler.Syntax.PropertyKeyword: Boolean get_IsAnd() -FSharp.Compiler.Syntax.PropertyKeyword: Boolean get_IsWith() -FSharp.Compiler.Syntax.PropertyKeyword: FSharp.Compiler.Syntax.PropertyKeyword NewAnd(FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.PropertyKeyword: FSharp.Compiler.Syntax.PropertyKeyword NewWith(FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.PropertyKeyword: FSharp.Compiler.Syntax.PropertyKeyword+And -FSharp.Compiler.Syntax.PropertyKeyword: FSharp.Compiler.Syntax.PropertyKeyword+Tags -FSharp.Compiler.Syntax.PropertyKeyword: FSharp.Compiler.Syntax.PropertyKeyword+With -FSharp.Compiler.Syntax.PropertyKeyword: Int32 Tag -FSharp.Compiler.Syntax.PropertyKeyword: Int32 get_Tag() -FSharp.Compiler.Syntax.PropertyKeyword: System.String ToString() FSharp.Compiler.Syntax.QualifiedNameOfFile FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Id FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Item @@ -7376,6 +7357,14 @@ FSharp.Compiler.Syntax.SynMemberDefn+AutoProperty: Microsoft.FSharp.Core.FSharpO FSharp.Compiler.Syntax.SynMemberDefn+AutoProperty: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_getSetRange() FSharp.Compiler.Syntax.SynMemberDefn+AutoProperty: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_withKeyword() FSharp.Compiler.Syntax.SynMemberDefn+AutoProperty: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] withKeyword +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia get_trivia() +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia trivia +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] get_memberDefnForGet() +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] get_memberDefnForSet() +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] memberDefnForGet +FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] memberDefnForSet FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynSimplePats ctorArgs FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynSimplePats get_ctorArgs() FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Text.Range get_range() @@ -7434,6 +7423,7 @@ FSharp.Compiler.Syntax.SynMemberDefn+Open: FSharp.Compiler.Text.Range get_range( FSharp.Compiler.Syntax.SynMemberDefn+Open: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynMemberDefn+Tags: Int32 AbstractSlot FSharp.Compiler.Syntax.SynMemberDefn+Tags: Int32 AutoProperty +FSharp.Compiler.Syntax.SynMemberDefn+Tags: Int32 GetSetMember FSharp.Compiler.Syntax.SynMemberDefn+Tags: Int32 ImplicitCtor FSharp.Compiler.Syntax.SynMemberDefn+Tags: Int32 ImplicitInherit FSharp.Compiler.Syntax.SynMemberDefn+Tags: Int32 Inherit @@ -7449,6 +7439,7 @@ FSharp.Compiler.Syntax.SynMemberDefn+ValField: FSharp.Compiler.Text.Range get_ra FSharp.Compiler.Syntax.SynMemberDefn+ValField: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsAbstractSlot FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsAutoProperty +FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsGetSetMember FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsImplicitCtor FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsImplicitInherit FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsInherit @@ -7460,6 +7451,7 @@ FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsOpen FSharp.Compiler.Syntax.SynMemberDefn: Boolean IsValField FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsAbstractSlot() FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsAutoProperty() +FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsGetSetMember() FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsImplicitCtor() FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsImplicitInherit() FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsInherit() @@ -7471,6 +7463,7 @@ FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsOpen() FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsValField() FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAbstractSlot(FSharp.Compiler.Syntax.SynValSig, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAutoProperty(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.Syntax.SynMemberKind, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynMemberKind,FSharp.Compiler.Syntax.SynMemberFlags], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewGetSetMember(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynSimplePats, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range) @@ -7482,6 +7475,7 @@ FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewOp FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewValField(FSharp.Compiler.Syntax.SynField, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn+AbstractSlot FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn+AutoProperty +FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn+ImplicitInherit FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn+Inherit @@ -7969,8 +7963,6 @@ FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] extraId FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] get_extraId() -FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.PropertyKeyword] get_propertyKeyword() -FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.PropertyKeyword] propertyKeyword FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] accessibility FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility() FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynValTyparDecls] get_typarDecls() @@ -8092,7 +8084,7 @@ FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewDeprecatedCharRa FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewFromParseError(FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewInstanceMember(FSharp.Compiler.Syntax.Ident, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewIsInst(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewLongIdent(FSharp.Compiler.Syntax.SynLongIdent, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.PropertyKeyword], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynValTyparDecls], FSharp.Compiler.Syntax.SynArgPats, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewLongIdent(FSharp.Compiler.Syntax.SynLongIdent, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynValTyparDecls], FSharp.Compiler.Syntax.SynArgPats, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewNamed(FSharp.Compiler.Syntax.SynIdent, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewNull(FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewOptionalVal(FSharp.Compiler.Syntax.Ident, FSharp.Compiler.Text.Range) @@ -9417,6 +9409,17 @@ FSharp.Compiler.SyntaxTrivia.SynMemberFlagsTrivia: Microsoft.FSharp.Core.FSharpO FSharp.Compiler.SyntaxTrivia.SynMemberFlagsTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_StaticRange() FSharp.Compiler.SyntaxTrivia.SynMemberFlagsTrivia: System.String ToString() FSharp.Compiler.SyntaxTrivia.SynMemberFlagsTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range]) +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: FSharp.Compiler.Text.Range WithKeyword +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: FSharp.Compiler.Text.Range get_WithKeyword() +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] AndKeyword +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] GetKeyword +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] SetKeyword +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_AndKeyword() +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_GetKeyword() +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_SetKeyword() +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia: Void .ctor(FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range]) FSharp.Compiler.SyntaxTrivia.SynModuleDeclNestedModuleTrivia FSharp.Compiler.SyntaxTrivia.SynModuleDeclNestedModuleTrivia: FSharp.Compiler.SyntaxTrivia.SynModuleDeclNestedModuleTrivia Zero FSharp.Compiler.SyntaxTrivia.SynModuleDeclNestedModuleTrivia: FSharp.Compiler.SyntaxTrivia.SynModuleDeclNestedModuleTrivia get_Zero() diff --git a/tests/service/ServiceUntypedParseTests.fs b/tests/service/ServiceUntypedParseTests.fs index 69fea1ce935..9917ec23d27 100644 --- a/tests/service/ServiceUntypedParseTests.fs +++ b/tests/service/ServiceUntypedParseTests.fs @@ -256,8 +256,7 @@ type T = with get () = x and set (value) = x <- value """ - getTypeMemberRange source |> shouldEqual [ (3, 4), (5, 36) - (3, 4), (5, 36) ] + getTypeMemberRange source |> shouldEqual [ (3, 4), (5, 36) ] [] diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 1ffd807d18d..7da84598b3b 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -661,8 +661,9 @@ type Foo() = | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ SynModuleDecl.Types( typeDefns = [ SynTypeDefn(typeRepr = - SynTypeDefnRepr.ObjectModel(members=[ _ - SynMemberDefn.Member(memberDefn=SynBinding(headPat=SynPat.LongIdent(propertyKeyword=Some(PropertyKeyword.With mWith)))) ]) + SynTypeDefnRepr.ObjectModel(members=[ + _ + SynMemberDefn.GetSetMember(Some(SynBinding _), None, _, { WithKeyword = mWith }) ]) ) ]) ]) ])) -> assertRange (4, 31) (4, 35) mWith @@ -682,8 +683,9 @@ type Foo() = | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ SynModuleDecl.Types( typeDefns = [ SynTypeDefn(typeRepr = - SynTypeDefnRepr.ObjectModel(members=[ _ - SynMemberDefn.Member(memberDefn=SynBinding(headPat=SynPat.LongIdent(propertyKeyword=Some(PropertyKeyword.With mWith)))) ]) + SynTypeDefnRepr.ObjectModel(members=[ + _ + SynMemberDefn.GetSetMember(None, Some(SynBinding _), _, { WithKeyword = mWith }) ]) ) ]) ]) ])) -> assertRange (4, 36) (4, 40) mWith @@ -705,9 +707,9 @@ type Foo() = | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ SynModuleDecl.Types( typeDefns = [ SynTypeDefn(typeRepr = - SynTypeDefnRepr.ObjectModel(members=[ _ - SynMemberDefn.Member(memberDefn=SynBinding(headPat=SynPat.LongIdent(propertyKeyword=Some(PropertyKeyword.With mWith)))) - SynMemberDefn.Member(memberDefn=SynBinding(headPat=SynPat.LongIdent(propertyKeyword=Some(PropertyKeyword.And mAnd)))) ]) + SynTypeDefnRepr.ObjectModel(members=[ + _ + SynMemberDefn.GetSetMember(Some _, Some _, _, { WithKeyword = mWith; AndKeyword = Some mAnd }) ]) ) ]) ]) ])) -> assertRange (5, 8) (5, 12) mWith @@ -754,6 +756,35 @@ type A = B assertRange (4, 0) (4, 4) mType | _ -> Assert.Fail "Could not get valid AST" + [] + let ``SynTypeDefn with static member with get/set`` () = + let parseResults = + getParseResults + """ +type Foo = + static member ReadWrite2 + with set x = lastUsed <- ("ReadWrite2", x) + and get () = lastUsed <- ("ReadWrite2", 0); 4 +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ + SynMemberDefn.GetSetMember(Some _, Some _, m, { WithKeyword = mWith + GetKeyword = Some mGet + AndKeyword = Some mAnd + SetKeyword = Some mSet }) + ])) ] + ) + ]) ])) -> + assertRange (4, 8) (4, 12) mWith + assertRange (4, 13) (4, 16) mSet + assertRange (5, 8) (5, 11) mAnd + assertRange (5, 13) (5, 16) mGet + assertRange (3, 4) (5, 54) m + | _ -> Assert.Fail "Could not get valid AST" + module SyntaxExpressions = [] let ``SynExpr.Do contains the range of the do keyword`` () = @@ -1218,6 +1249,33 @@ global assertRange (1,0) (1, 8) mSetExpr | _ -> Assert.Fail $"Could not get valid AST, got {ast}" + [] + let ``SynExpr.Obj with setter`` () = + let ast = + getParseResults """ +[] +type CFoo() = + abstract AbstractClassPropertySet: string with set + +{ new CFoo() with + override this.AbstractClassPropertySet with set (v:string) = () } +""" + + match ast with + | ParsedInput.ImplFile(ParsedImplFileInput(modules = [ + SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types _ + SynModuleDecl.Expr(expr = SynExpr.ObjExpr(members = [ + SynMemberDefn.GetSetMember(None, Some _, m, { WithKeyword = mWith; SetKeyword = Some mSet }) + ])) + ]) + ])) -> + assertRange (7, 43) (7, 47) mWith + assertRange (7, 48) (7, 51) mSet + assertRange (7,4) (7, 67) m + | _ -> Assert.Fail $"Could not get valid AST, got {ast}" + + module Strings = let getBindingExpressionValue (parseResults: ParsedInput) = match parseResults with @@ -2571,7 +2629,8 @@ type Crane = match parseResults with | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [SynMemberDefn.Member(memberDefn = SynBinding(range = mb)) as m]))]) + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = + [SynMemberDefn.GetSetMember(memberDefnForSet = Some (SynBinding(range = mb))) as m]))]) ]) ])) -> assertRange (3, 4) (4, 52) mb assertRange (3, 4) (4, 79) m.Range @@ -2591,14 +2650,12 @@ type Bird = match parseResults with | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ - SynMemberDefn.Member(memberDefn = SynBinding(range = mb1)) as getter - SynMemberDefn.Member(memberDefn = SynBinding(range = mb2)) as setter + SynMemberDefn.GetSetMember(Some (SynBinding(range = mb1)), Some (SynBinding(range = mb2)), m, _) ]))]) ]) ])) -> assertRange (3, 4) (5, 19) mb1 - assertRange (3, 4) (6, 50) getter.Range assertRange (3, 4) (6, 23) mb2 - assertRange (3, 4) (6, 50) setter.Range + assertRange (3, 4) (6, 50) m | _ -> Assert.Fail "Could not get valid AST" [] @@ -2722,8 +2779,9 @@ type Y() = | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ _ - SynMemberDefn.Member(memberDefn = SynBinding(trivia={ EqualsRange = Some eqGetM })) - SynMemberDefn.Member(memberDefn = SynBinding(trivia={ EqualsRange = Some eqSetM })) + SynMemberDefn.GetSetMember( + Some(SynBinding(trivia={ EqualsRange = Some eqGetM })), + Some(SynBinding(trivia={ EqualsRange = Some eqSetM })), _, _) ]))]) ]) ])) -> assertRange (4, 20) (4, 21) eqGetM @@ -4603,10 +4661,11 @@ type X() = SynTypeDefn.SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members =[ SynMemberDefn.ImplicitCtor _ SynMemberDefn.LetBindings _ - SynMemberDefn.Member(memberDefn = SynBinding(headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ _ ; allowIntoPatternGet ]) - propertyKeyword = Some (PropertyKeyword.With mWith)))) - SynMemberDefn.Member(memberDefn = SynBinding(headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ _ ; allowIntoPatternSet ]) - propertyKeyword = Some (PropertyKeyword.And mAnd)))) + SynMemberDefn.GetSetMember( + Some (SynBinding(headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ _ ; allowIntoPatternGet ])))), + Some (SynBinding(headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ _ ; allowIntoPatternSet ])))), + _, + { WithKeyword = mWith; AndKeyword = Some mAnd }) ])) ]) ]) diff --git a/tests/service/XmlDocTests.fs b/tests/service/XmlDocTests.fs index 2a37cd53afe..76bce785065 100644 --- a/tests/service/XmlDocTests.fs +++ b/tests/service/XmlDocTests.fs @@ -897,7 +897,7 @@ type B = |] match parseResults.ParseTree with - | Members(SynMemberDefn.Member(range = range; memberDefn = SynBinding(xmlDoc = xmlDoc) as binding) :: _) -> + | Members([ SynMemberDefn.GetSetMember(Some (SynBinding(xmlDoc = xmlDoc) as binding), _, range, _); _ ]) -> assertRange (3, 4) (10, 37) range assertRange (3, 4) (8, 37) binding.RangeOfBindingWithRhs assertRange (3, 4) (4, 9) xmlDoc.Range