Skip to content

Commit 027424c

Browse files
auduchinokbaronfel
authored andcommitted
Attributes lists (#6830)
* Preserve attributes lists in AST * Add attribute list test
1 parent a2024d1 commit 027424c

File tree

7 files changed

+137
-65
lines changed

7 files changed

+137
-65
lines changed

src/fsharp/TypeChecker.fs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ let AdjustValSynInfoInSignature g ty (SynValInfo(argsData, retData) as sigMD) =
962962
/// The ValReprInfo for a value, except the number of typars is not yet inferred
963963
type PartialValReprInfo = PartialValReprInfo of ArgReprInfo list list * ArgReprInfo
964964

965-
let TranslateTopArgSynInfo isArg m tcAttributes (SynArgInfo(attrs, isOpt, nm)) =
965+
let TranslateTopArgSynInfo isArg m tcAttributes (SynArgInfo(Attributes attrs, isOpt, nm)) =
966966
// Synthesize an artificial "OptionalArgument" attribute for the parameter
967967
let optAttrs =
968968
if isOpt then
@@ -2453,7 +2453,7 @@ type NormalizedBinding =
24532453
SynBindingKind *
24542454
bool * (* pesudo/mustinline value? *)
24552455
bool * (* mutable *)
2456-
SynAttributes *
2456+
SynAttribute list *
24572457
XmlDoc *
24582458
SynValTyparDecls *
24592459
SynValData *
@@ -2583,7 +2583,7 @@ module BindingNormalization =
25832583

25842584
let NormalizeBinding isObjExprBinding cenv (env: TcEnv) b =
25852585
match b with
2586-
| Binding (vis, bkind, isInline, isMutable, attrs, doc, valSynData, p, retInfo, rhsExpr, mBinding, spBind) ->
2586+
| Binding (vis, bkind, isInline, isMutable, Attributes attrs, doc, valSynData, p, retInfo, rhsExpr, mBinding, spBind) ->
25872587
let (NormalizedBindingPat(pat, rhsExpr, valSynData, typars)) =
25882588
NormalizeBindingPattern cenv cenv.nameResolver isObjExprBinding env valSynData p (NormalizedBindingRhs ([], retInfo, rhsExpr))
25892589
NormalizedBinding(vis, bkind, isInline, isMutable, attrs, doc.ToXmlDoc(), typars, valSynData, pat, rhsExpr, mBinding, spBind)
@@ -4572,7 +4572,7 @@ and TcTyparOrMeasurePar optKind cenv (env: TcEnv) newOk tpenv (Typar(id, _, _) a
45724572
and TcTypar cenv env newOk tpenv tp =
45734573
TcTyparOrMeasurePar (Some TyparKind.Type) cenv env newOk tpenv tp
45744574

4575-
and TcTyparDecl cenv env (TyparDecl(synAttrs, (Typar(id, _, _) as stp))) =
4575+
and TcTyparDecl cenv env (TyparDecl(Attributes synAttrs, (Typar(id, _, _) as stp))) =
45764576
let attrs = TcAttributes cenv env AttributeTargets.GenericParameter synAttrs
45774577
let hasMeasureAttr = HasFSharpAttribute cenv.g cenv.g.attrib_MeasureAttribute attrs
45784578
let hasEqDepAttr = HasFSharpAttribute cenv.g cenv.g.attrib_EqualityConditionalOnAttribute attrs
@@ -10763,7 +10763,7 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
1076310763
spatsL |> List.map (SynInfo.InferSynArgInfoFromSimplePats >> List.map (SynInfo.AttribsOfArgData >> TcAttrs AttributeTargets.Parameter))
1076410764
let retAttribs =
1076510765
match rtyOpt with
10766-
| Some (SynBindingReturnInfo(_, _, retAttrs)) -> TcAttrs AttributeTargets.ReturnValue retAttrs
10766+
| Some (SynBindingReturnInfo(_, _, Attributes retAttrs)) -> TcAttrs AttributeTargets.ReturnValue retAttrs
1076710767
| None -> []
1076810768

1076910769
let argAndRetAttribs = ArgAndRetAttribs(argAttribs, retAttribs)
@@ -12289,7 +12289,7 @@ and TcLetrec overridesOK cenv env tpenv (binds, bindsm, scopem) =
1228912289

1229012290
let TcAndPublishValSpec (cenv, env, containerInfo: ContainerInfo, declKind, memFlagsOpt, tpenv, valSpfn) =
1229112291

12292-
let (ValSpfn (synAttrs, _, SynValTyparDecls (synTypars, synCanInferTypars, _), _, _, isInline, mutableFlag, doc, vis, literalExprOpt, m)) = valSpfn
12292+
let (ValSpfn (Attributes synAttrs, _, SynValTyparDecls (synTypars, synCanInferTypars, _), _, _, isInline, mutableFlag, doc, vis, literalExprOpt, m)) = valSpfn
1229312293

1229412294
GeneralizationHelpers.CheckDeclaredTyparsPermitted(memFlagsOpt, synTypars, m)
1229512295
let canInferTypars = GeneralizationHelpers.ComputeCanInferExtraGeneralizableTypars (containerInfo.ParentRef, synCanInferTypars, memFlagsOpt)
@@ -12405,7 +12405,7 @@ module TcRecdUnionAndEnumDeclarations = begin
1240512405
rfspec
1240612406

1240712407

12408-
let TcAnonFieldDecl cenv env parent tpenv nm (Field(attribs, isStatic, idOpt, ty, isMutable, xmldoc, vis, m)) =
12408+
let TcAnonFieldDecl cenv env parent tpenv nm (Field(Attributes attribs, isStatic, idOpt, ty, isMutable, xmldoc, vis, m)) =
1240912409
let id = (match idOpt with None -> mkSynId m nm | Some id -> id)
1241012410
let f = TcFieldDecl cenv env parent false tpenv (isStatic, attribs, id, idOpt.IsNone, ty, isMutable, xmldoc.ToXmlDoc(), vis, m)
1241112411
match idOpt with
@@ -12416,7 +12416,7 @@ module TcRecdUnionAndEnumDeclarations = begin
1241612416
f
1241712417

1241812418

12419-
let TcNamedFieldDecl cenv env parent isIncrClass tpenv (Field(attribs, isStatic, id, ty, isMutable, xmldoc, vis, m)) =
12419+
let TcNamedFieldDecl cenv env parent isIncrClass tpenv (Field(Attributes attribs, isStatic, id, ty, isMutable, xmldoc, vis, m)) =
1242012420
match id with
1242112421
| None -> error (Error(FSComp.SR.tcFieldRequiresName(), m))
1242212422
| Some id -> TcFieldDecl cenv env parent isIncrClass tpenv (isStatic, attribs, id, false, ty, isMutable, xmldoc.ToXmlDoc(), vis, m)
@@ -12453,7 +12453,7 @@ module TcRecdUnionAndEnumDeclarations = begin
1245312453
| _ ->
1245412454
seen.Add(f.Name, sf)
1245512455

12456-
let TcUnionCaseDecl cenv env parent thisTy tpenv (UnionCase (synAttrs, id, args, xmldoc, vis, m)) =
12456+
let TcUnionCaseDecl cenv env parent thisTy tpenv (UnionCase(Attributes synAttrs, id, args, xmldoc, vis, m)) =
1245712457
let attrs = TcAttributes cenv env AttributeTargets.UnionCaseDecl synAttrs // the attributes of a union case decl get attached to the generated "static factory" method
1245812458
let vis, _ = ComputeAccessAndCompPath env None m vis None parent
1245912459
let vis = CombineReprAccess parent vis
@@ -12490,7 +12490,7 @@ module TcRecdUnionAndEnumDeclarations = begin
1249012490
let unionCases' = unionCases |> List.map (TcUnionCaseDecl cenv env parent thisTy tpenv)
1249112491
unionCases' |> CheckDuplicates (fun uc -> uc.Id) "union case"
1249212492

12493-
let TcEnumDecl cenv env parent thisTy fieldTy (EnumCase (synAttrs, id, v, xmldoc, m)) =
12493+
let TcEnumDecl cenv env parent thisTy fieldTy (EnumCase(Attributes synAttrs, id, v, xmldoc, m)) =
1249412494
let attrs = TcAttributes cenv env AttributeTargets.Field synAttrs
1249512495
match v with
1249612496
| SynConst.Bytes _
@@ -13556,7 +13556,7 @@ module MutRecBindingChecking =
1355613556
error(Error(FSComp.SR.tcEnumerationsMayNotHaveMembers(), (trimRangeToLine m)))
1355713557

1355813558
match classMemberDef, containerInfo with
13559-
| SynMemberDefn.ImplicitCtor (vis, attrs, spats, thisIdOpt, m), ContainerInfo(_, Some(MemberOrValContainerInfo(tcref, _, baseValOpt, safeInitInfo, _))) ->
13559+
| SynMemberDefn.ImplicitCtor (vis, Attributes attrs, spats, thisIdOpt, m), ContainerInfo(_, Some(MemberOrValContainerInfo(tcref, _, baseValOpt, safeInitInfo, _))) ->
1356013560
if tcref.TypeOrMeasureKind = TyparKind.Measure then
1356113561
error(Error(FSComp.SR.tcMeasureDeclarationsRequireStaticMembers(), m))
1356213562

@@ -14810,7 +14810,7 @@ let CheckForDuplicateModule env nm m =
1481014810
/// Check 'exception' declarations in implementations and signatures
1481114811
module TcExceptionDeclarations =
1481214812

14813-
let TcExnDefnCore_Phase1A cenv env parent (SynExceptionDefnRepr(synAttrs, UnionCase(_, id, _, _, _, _), _, doc, vis, m)) =
14813+
let TcExnDefnCore_Phase1A cenv env parent (SynExceptionDefnRepr(Attributes synAttrs, UnionCase(_, id, _, _, _, _), _, doc, vis, m)) =
1481414814
let attrs = TcAttributes cenv env AttributeTargets.ExnDecl synAttrs
1481514815
if not (String.isUpper id.idText) then errorR(NotUpperCaseConstructor m)
1481614816
let vis, cpath = ComputeAccessAndCompPath env None m vis None parent
@@ -15075,7 +15075,7 @@ module EstablishTypeDefinitionCores =
1507515075
|> set
1507615076

1507715077
let TcTyconDefnCore_Phase1A_BuildInitialModule cenv envInitial parent typeNames compInfo decls =
15078-
let (ComponentInfo(attribs, _parms, _constraints, longPath, xml, _, vis, im)) = compInfo
15078+
let (ComponentInfo(Attributes attribs, _parms, _constraints, longPath, xml, _, vis, im)) = compInfo
1507915079
let id = ComputeModuleName longPath
1508015080
let modAttrs = TcAttributes cenv envInitial AttributeTargets.ModuleDecl attribs
1508115081
let modKind = ComputeModuleOrNamespaceKind cenv.g true typeNames modAttrs id.idText
@@ -15146,7 +15146,7 @@ module EstablishTypeDefinitionCores =
1514615146
/// synTyconInfo: Syntactic AST for the name, attributes etc. of the type constructor
1514715147
/// synTyconRepr: Syntactic AST for the RHS of the type definition
1514815148
let private TcTyconDefnCore_Phase1B_EstablishBasicKind cenv inSig envinner (MutRecDefnsPhase1DataForTycon(synTyconInfo, synTyconRepr, _, _, _, _)) (tycon: Tycon) =
15149-
let (ComponentInfo(synAttrs, typars, _, _, _, _, _, _)) = synTyconInfo
15149+
let (ComponentInfo(Attributes synAttrs, typars, _, _, _, _, _, _)) = synTyconInfo
1515015150
let m = tycon.Range
1515115151
let id = tycon.Id
1515215152

@@ -16520,7 +16520,7 @@ module TcDeclarations =
1652016520
// Convert autoproperties to let bindings in the pre-list
1652116521
let rec preAutoProps memb =
1652216522
match memb with
16523-
| SynMemberDefn.AutoProperty (attribs, isStatic, id, tyOpt, propKind, _, xmlDoc, _access, synExpr, _mGetSet, mWholeAutoProp) ->
16523+
| SynMemberDefn.AutoProperty(Attributes attribs, isStatic, id, tyOpt, propKind, _, xmlDoc, _access, synExpr, _mGetSet, mWholeAutoProp) ->
1652416524
// Only the keep the field-targeted attributes
1652516525
let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> true | _ -> false)
1652616526
let mLetPortion = synExpr.Range
@@ -16532,6 +16532,7 @@ module TcDeclarations =
1653216532
| MemberKind.PropertySet
1653316533
| MemberKind.PropertyGetSet -> true
1653416534
| _ -> false
16535+
let attribs = mkAttributeList attribs mWholeAutoProp
1653516536
let binding = mkSynBinding (xmlDoc, headPat) (None, false, isMutable, mLetPortion, NoSequencePointAtInvisibleBinding, retInfo, synExpr, synExpr.Range, [], attribs, None)
1653616537

1653716538
[(SynMemberDefn.LetBindings ([binding], isStatic, false, mWholeAutoProp))]
@@ -16546,7 +16547,7 @@ module TcDeclarations =
1654616547
// Convert autoproperties to member bindings in the post-list
1654716548
let rec postAutoProps memb =
1654816549
match memb with
16549-
| SynMemberDefn.AutoProperty (attribs, isStatic, id, tyOpt, propKind, memberFlags, xmlDoc, access, _synExpr, mGetSetOpt, _mWholeAutoProp) ->
16550+
| SynMemberDefn.AutoProperty(Attributes attribs, isStatic, id, tyOpt, propKind, memberFlags, xmlDoc, access, _synExpr, mGetSetOpt, _mWholeAutoProp) ->
1655016551
let mMemberPortion = id.idRange
1655116552
// Only the keep the non-field-targeted attributes
1655216553
let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> false | _ -> true)
@@ -16566,6 +16567,7 @@ module TcDeclarations =
1656616567
let getter =
1656716568
let rhsExpr = SynExpr.Ident fldId
1656816569
let retInfo = match tyOpt with None -> None | Some ty -> Some (SynReturnInfo((ty, SynInfo.unnamedRetVal), ty.Range))
16570+
let attribs = mkAttributeList attribs mMemberPortion
1656916571
let binding = mkSynBinding (xmlDoc, headPat) (access, false, false, mMemberPortion, NoSequencePointAtInvisibleBinding, retInfo, rhsExpr, rhsExpr.Range, [], attribs, Some (memberFlags MemberKind.Member))
1657016572
SynMemberDefn.Member (binding, mMemberPortion)
1657116573
yield getter
@@ -16870,7 +16872,7 @@ let rec TcSignatureElementNonMutRec cenv parent typeNames endm (env: TcEnv) synS
1687016872
let env = List.foldBack (AddLocalVal cenv.tcSink scopem) idvs env
1687116873
return env
1687216874

16873-
| SynModuleSigDecl.NestedModule(ComponentInfo(attribs, _parms, _constraints, longPath, xml, _, vis, im) as compInfo, isRec, mdefs, m) ->
16875+
| SynModuleSigDecl.NestedModule(ComponentInfo(Attributes attribs, _parms, _constraints, longPath, xml, _, vis, im) as compInfo, isRec, mdefs, m) ->
1687416876
if isRec then
1687516877
// Treat 'module rec M = ...' as a single mutually recursive definition group 'module M = ...'
1687616878
let modDecl = SynModuleSigDecl.NestedModule(compInfo, false, mdefs, m)
@@ -17175,7 +17177,7 @@ let rec TcModuleOrNamespaceElementNonMutRec (cenv: cenv) parent typeNames scopem
1717517177

1717617178
| SynModuleDecl.DoExpr _ -> return! failwith "unreachable"
1717717179

17178-
| SynModuleDecl.Attributes (synAttrs, _) ->
17180+
| SynModuleDecl.Attributes (Attributes synAttrs, _) ->
1717917181
let attrs, _ = TcAttributesWithPossibleTargets false cenv env AttributeTargets.Top synAttrs
1718017182
return ((fun e -> e), attrs), env, env
1718117183

@@ -17190,7 +17192,7 @@ let rec TcModuleOrNamespaceElementNonMutRec (cenv: cenv) parent typeNames scopem
1719017192
let modDecl = SynModuleDecl.NestedModule(compInfo, false, mdefs, isContinuingModule, m)
1719117193
return! TcModuleOrNamespaceElementsMutRec cenv parent typeNames m env None [modDecl]
1719217194
else
17193-
let (ComponentInfo(attribs, _parms, _constraints, longPath, xml, _, vis, im)) = compInfo
17195+
let (ComponentInfo(Attributes attribs, _parms, _constraints, longPath, xml, _, vis, im)) = compInfo
1719417196
let id = ComputeModuleName longPath
1719517197

1719617198
let modAttrs = TcAttributes cenv env AttributeTargets.ModuleDecl attribs
@@ -17327,7 +17329,7 @@ and TcModuleOrNamespaceElementsMutRec cenv parent typeNames endm envInitial mutR
1732717329
let m = match defs with [] -> endm | _ -> defs |> List.map (fun d -> d.Range) |> List.reduce unionRanges
1732817330
let scopem = (defs, endm) ||> List.foldBack (fun h m -> unionRanges h.Range m)
1732917331

17330-
let (mutRecDefns, (_, _, synAttrs)) =
17332+
let (mutRecDefns, (_, _, Attributes synAttrs)) =
1733117333
let rec loop isNamespace attrs defs: (MutRecDefnsInitialData * _) =
1733217334
((true, true, attrs), defs) ||> List.collectFold (fun (openOk, moduleAbbrevOk, attrs) def ->
1733317335
match ElimModuleDoBinding def with

src/fsharp/ast.fs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,13 @@ and
11721172
| None -> unionRanges e.Range m
11731173
| Some x -> unionRanges (unionRanges e.Range m) x.Range
11741174

1175-
and SynAttributes = SynAttribute list
1175+
and
1176+
/// List of attributes enclosed in [< ... >].
1177+
SynAttributeList =
1178+
{ Attributes: SynAttribute list
1179+
Range: range }
1180+
1181+
and SynAttributes = SynAttributeList list
11761182

11771183
and
11781184
[<NoEquality; NoComparison; RequireQualifiedAccess>]
@@ -2118,6 +2124,18 @@ type SynExpr with
21182124
type SynReturnInfo = SynReturnInfo of (SynType * SynArgInfo) * range: range
21192125

21202126

2127+
let mkAttributeList attrs range =
2128+
[{ Attributes = attrs
2129+
Range = range }]
2130+
2131+
let ConcatAttributesLists (attrsLists: SynAttributeList list) =
2132+
attrsLists
2133+
|> List.map (fun x -> x.Attributes)
2134+
|> List.concat
2135+
2136+
let (|Attributes|) synAttributes =
2137+
ConcatAttributesLists synAttributes
2138+
21212139
/// Operations related to the syntactic analysis of arguments of value, function and member definitions and signatures.
21222140
///
21232141
/// Function and member definitions have strongly syntactically constrained arities. We infer
@@ -2186,7 +2204,7 @@ module SynInfo =
21862204
let AritiesOfArgs (SynValInfo(args, _)) = List.map List.length args
21872205

21882206
/// Get the argument attributes from the syntactic information for an argument.
2189-
let AttribsOfArgData (SynArgInfo(attribs, _, _)) = attribs
2207+
let AttribsOfArgData (SynArgInfo(Attributes attribs, _, _)) = attribs
21902208

21912209
/// Infer the syntactic argument info for a single argument from a simple pattern.
21922210
let rec InferSynArgInfoFromSimplePat attribs p =

src/fsharp/pars.fsy

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,20 +1357,20 @@ attributes:
13571357

13581358

13591359
/* One set of custom attributes, including [< ... >] */
1360-
attributeList:
1361-
| LBRACK_LESS attributeListElements opt_seps GREATER_RBRACK opt_OBLOCKSEP
1362-
{ $2 }
1360+
attributeList:
1361+
| LBRACK_LESS attributeListElements opt_seps GREATER_RBRACK opt_OBLOCKSEP
1362+
{ mkAttributeList $2 (rhs2 parseState 1 3) }
13631363

1364-
| LBRACK_LESS error GREATER_RBRACK opt_OBLOCKSEP
1365-
{ [] }
1364+
| LBRACK_LESS error GREATER_RBRACK opt_OBLOCKSEP
1365+
{ mkAttributeList [] (rhs2 parseState 1 3) }
13661366

1367-
| LBRACK_LESS attributeListElements opt_seps ends_coming_soon_or_recover
1367+
| LBRACK_LESS attributeListElements opt_seps ends_coming_soon_or_recover
13681368
{ if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedLBrackLess())
1369-
$2 }
1369+
mkAttributeList $2 (rhs2 parseState 1 2) }
13701370

1371-
| LBRACK_LESS ends_coming_soon_or_recover
1371+
| LBRACK_LESS ends_coming_soon_or_recover
13721372
{ if not $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedLBrackLess())
1373-
[] }
1373+
mkAttributeList [] (rhs parseState 1) }
13741374

13751375

13761376
/* One set of custom attributes, not including [< ... >] */
@@ -1644,7 +1644,10 @@ memberCore:
16441644
let optInline = $1 || optInline
16451645
// optional attributes are only applied to getters and setters
16461646
// the "top level" attrs will be applied to both
1647-
let optAttrs = optAttrs |> List.map (fun (a:SynAttribute) -> { a with AppliesToGetterAndSetter=true })
1647+
let optAttrs =
1648+
optAttrs |> List.map (fun attrList ->
1649+
{ attrList with Attributes = attrList.Attributes |> List.map (fun a -> { a with AppliesToGetterAndSetter = true } ) })
1650+
16481651
let attrs = attrs @ optAttrs
16491652

16501653
let binding = bindingBuilder (visNoLongerUsed,optInline,isMutable,mBindLhs,NoSequencePointAtInvisibleBinding,optReturnType,expr,exprm,[],attrs,Some (memFlagsBuilder MemberKind.Member))

0 commit comments

Comments
 (0)