@@ -178,6 +178,12 @@ type SyntaxVisitorBase<'T>() =
178178 ignore path
179179 defaultTraverse synType
180180
181+ abstract VisitAttributeApplication: path : SyntaxVisitorPath * attributes : SynAttributeList -> 'T option
182+
183+ default _.VisitAttributeApplication ( path , attributes ) =
184+ ignore ( path, attributes)
185+ None
186+
181187/// A range of utility functions to assist with traversing an AST
182188module SyntaxTraversal =
183189
@@ -278,9 +284,10 @@ module SyntaxTraversal =
278284
279285 match m with
280286 | SynModuleDecl.ModuleAbbrev (_ ident, _ longIdent, _ range) -> None
281- | SynModuleDecl.NestedModule ( decls = synModuleDecls) ->
287+ | SynModuleDecl.NestedModule ( decls = synModuleDecls; moduleInfo = SynComponentInfo ( attributes = attributes ) ) ->
282288 synModuleDecls
283289 |> List.map ( fun x -> dive x x.Range ( traverseSynModuleDecl path))
290+ |> List.append ( attributeApplicationDives path attributes)
284291 |> pick decl
285292 | SynModuleDecl.Let ( isRecursive, synBindingList, range) ->
286293 match visitor.VisitLetOrUse( path, isRecursive, traverseSynBinding path, synBindingList, range) with
@@ -296,7 +303,7 @@ module SyntaxTraversal =
296303 |> pick decl
297304 | SynModuleDecl.Exception (_ synExceptionDefn, _ range) -> None
298305 | SynModuleDecl.Open (_ target, _ range) -> None
299- | SynModuleDecl.Attributes (_ synAttributes , _ range ) -> None
306+ | SynModuleDecl.Attributes ( attributes , _ ) -> attributeApplicationDives path attributes |> pick decl
300307 | SynModuleDecl.HashDirective ( parsedHashDirective, range) -> visitor.VisitHashDirective( path, parsedHashDirective, range)
301308 | SynModuleDecl.NamespaceFragment ( synModuleOrNamespace) -> traverseSynModuleOrNamespace path synModuleOrNamespace
302309
@@ -549,7 +556,7 @@ module SyntaxTraversal =
549556 | SynExpr.Lambda ( args = synSimplePats; body = synExpr) ->
550557 match synSimplePats with
551558 | SynSimplePats.SimplePats ( pats, _) ->
552- match visitor.VisitSimplePats ( path, pats) with
559+ match traverseSynSimplePats path pats with
553560 | None -> traverseSynExpr synExpr
554561 | x -> x
555562 | _ -> traverseSynExpr synExpr
@@ -792,7 +799,10 @@ module SyntaxTraversal =
792799 | SynPat.Ands ( ps, _)
793800 | SynPat.Tuple (_, ps, _)
794801 | SynPat.ArrayOrList (_, ps, _) -> ps |> List.tryPick ( traversePat path)
795- | SynPat.Attrib ( p, _, _) -> traversePat path p
802+ | SynPat.Attrib ( p, attributes, m) ->
803+ match traversePat path p with
804+ | None -> attributeApplicationDives path attributes |> pick m attributes
805+ | x -> x
796806 | SynPat.LongIdent ( argPats = args) ->
797807 match args with
798808 | SynArgPats.Pats ps -> ps |> List.tryPick ( traversePat path)
@@ -805,6 +815,17 @@ module SyntaxTraversal =
805815
806816 visitor.VisitPat( origPath, defaultTraverse, pat)
807817
818+ and traverseSynSimplePats origPath ( pats : SynSimplePat list ) =
819+ match visitor.VisitSimplePats( origPath, pats) with
820+ | None ->
821+ pats
822+ |> List.tryPick ( fun pat ->
823+ match pat with
824+ | SynSimplePat.Attrib ( attributes = attributes; range = m) ->
825+ attributeApplicationDives origPath attributes |> pick m attributes
826+ | _ -> None)
827+ | x -> x
828+
808829 and traverseSynType origPath ( StripParenTypes ty ) =
809830 let defaultTraverse ty =
810831 let path = SyntaxNode.SynType ty :: origPath
@@ -854,36 +875,64 @@ module SyntaxTraversal =
854875 match visitor.VisitComponentInfo( origPath, synComponentInfo) with
855876 | Some x -> Some x
856877 | None ->
857- [
858- match synTypeDefnRepr with
859- | SynTypeDefnRepr.Exception _ ->
860- // This node is generated in CheckExpressions.fs, not in the AST.
861- // But note exception declarations are missing from this tree walk.
862- ()
863- | SynTypeDefnRepr.ObjectModel ( synTypeDefnKind, synMemberDefns, _ oRange) ->
864- // traverse inherit function is used to capture type specific data required for processing Inherit part
865- let traverseInherit ( synType : SynType , range : range ) =
866- visitor.VisitInheritSynMemberDefn( path, synComponentInfo, synTypeDefnKind, synType, synMemberDefns, range)
878+ match synComponentInfo with
879+ | SynComponentInfo ( attributes = attributes) ->
880+ [
881+ yield ! attributeApplicationDives path attributes
882+
883+ match synTypeDefnRepr with
884+ | SynTypeDefnRepr.Exception _ ->
885+ // This node is generated in CheckExpressions.fs, not in the AST.
886+ // But note exception declarations are missing from this tree walk.
887+ ()
888+ | SynTypeDefnRepr.ObjectModel ( synTypeDefnKind, synMemberDefns, _ oRange) ->
889+ // traverse inherit function is used to capture type specific data required for processing Inherit part
890+ let traverseInherit ( synType : SynType , range : range ) =
891+ visitor.VisitInheritSynMemberDefn( path, synComponentInfo, synTypeDefnKind, synType, synMemberDefns, range)
867892
893+ yield !
894+ synMemberDefns
895+ |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path traverseInherit
896+ | SynTypeDefnRepr.Simple ( synTypeDefnSimpleRepr, _ range) ->
897+ match synTypeDefnSimpleRepr with
898+ | SynTypeDefnSimpleRepr.Record (_ synAccessOption, fields, m) ->
899+ yield dive () synTypeDefnRepr.Range ( fun () -> traverseRecordDefn path fields m)
900+ | SynTypeDefnSimpleRepr.Union (_ synAccessOption, cases, m) ->
901+ yield dive () synTypeDefnRepr.Range ( fun () -> traverseUnionDefn path cases m)
902+ | SynTypeDefnSimpleRepr.Enum ( cases, m) ->
903+ yield dive () synTypeDefnRepr.Range ( fun () -> traverseEnumDefn path cases m)
904+ | SynTypeDefnSimpleRepr.TypeAbbrev (_, synType, m) ->
905+ yield dive synTypeDefnRepr synTypeDefnRepr.Range ( fun _ -> visitor.VisitTypeAbbrev( path, synType, m))
906+ | _ -> ()
868907 yield !
869908 synMemberDefns
870- |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path traverseInherit
871- | SynTypeDefnRepr.Simple ( synTypeDefnSimpleRepr, _ range) ->
872- match synTypeDefnSimpleRepr with
873- | SynTypeDefnSimpleRepr.Record (_ synAccessOption, fields, m) ->
874- yield dive () synTypeDefnRepr.Range ( fun () -> visitor.VisitRecordDefn( path, fields, m))
875- | SynTypeDefnSimpleRepr.Union (_ synAccessOption, cases, m) ->
876- yield dive () synTypeDefnRepr.Range ( fun () -> visitor.VisitUnionDefn( path, cases, m))
877- | SynTypeDefnSimpleRepr.Enum ( cases, m) ->
878- yield dive () synTypeDefnRepr.Range ( fun () -> visitor.VisitEnumDefn( path, cases, m))
879- | SynTypeDefnSimpleRepr.TypeAbbrev (_, synType, m) ->
880- yield dive synTypeDefnRepr synTypeDefnRepr.Range ( fun _ -> visitor.VisitTypeAbbrev( path, synType, m))
881- | _ -> ()
882- yield !
883- synMemberDefns
884- |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path ( fun _ -> None)
885- ]
886- |> pick tRange tydef
909+ |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path ( fun _ -> None)
910+ ]
911+ |> pick tRange tydef
912+
913+ and traverseRecordDefn path fields m =
914+ fields
915+ |> List.tryPick ( fun ( SynField ( attributes = attributes )) -> attributeApplicationDives path attributes |> pick m attributes)
916+ |> Option.orElseWith ( fun () -> visitor.VisitRecordDefn( path, fields, m))
917+
918+ and traverseEnumDefn path cases m =
919+ cases
920+ |> List.tryPick ( fun ( SynEnumCase ( attributes = attributes )) -> attributeApplicationDives path attributes |> pick m attributes)
921+ |> Option.orElseWith ( fun () -> visitor.VisitEnumDefn( path, cases, m))
922+
923+ and traverseUnionDefn path cases m =
924+ cases
925+ |> List.tryPick ( fun ( SynUnionCase ( attributes = attributes ; caseType = caseType )) ->
926+ match attributeApplicationDives path attributes |> pick m attributes with
927+ | None ->
928+ match caseType with
929+ | SynUnionCaseKind.Fields fields ->
930+ fields
931+ |> List.tryPick ( fun ( SynField ( attributes = attributes )) ->
932+ attributeApplicationDives path attributes |> pick m attributes)
933+ | _ -> None
934+ | x -> x)
935+ |> Option.orElseWith ( fun () -> visitor.VisitUnionDefn( path, cases, m))
887936
888937 and traverseSynMemberDefn path traverseInherit ( m : SynMemberDefn ) =
889938 let pick ( debugObj : obj ) = pick m.Range debugObj
@@ -903,7 +952,7 @@ module SyntaxTraversal =
903952
904953 | SynMemberDefn.ImplicitCtor ( ctorArgs = simplePats) ->
905954 match simplePats with
906- | SynSimplePats.SimplePats ( simplePats, _) -> visitor.VisitSimplePats ( path, simplePats)
955+ | SynSimplePats.SimplePats ( simplePats, _) -> traverseSynSimplePats path simplePats
907956 | _ -> None
908957 | SynMemberDefn.ImplicitInherit ( synType, synExpr, _ identOption, range) ->
909958 [
@@ -914,15 +963,21 @@ module SyntaxTraversal =
914963 dive () synExpr.Range ( fun () -> visitor.VisitImplicitInherit( path, traverseSynExpr path, synType, synExpr, range))
915964 ]
916965 |> pick m
917- | SynMemberDefn.AutoProperty ( synExpr = synExpr) -> traverseSynExpr path synExpr
966+ | SynMemberDefn.AutoProperty ( synExpr = synExpr; attributes = attributes) ->
967+ match traverseSynExpr path synExpr with
968+ | None -> attributeApplicationDives path attributes |> pick attributes
969+ | x -> x
918970 | SynMemberDefn.LetBindings ( synBindingList, isRecursive, _, range) ->
919971 match visitor.VisitLetOrUse( path, isRecursive, traverseSynBinding path, synBindingList, range) with
920972 | None ->
921973 synBindingList
922974 |> List.map ( fun x -> dive x x.RangeOfBindingWithRhs ( traverseSynBinding path))
923975 |> pick m
924976 | x -> x
925- | SynMemberDefn.AbstractSlot( slotSig = SynValSig ( synType = synType)) -> traverseSynType path synType
977+ | SynMemberDefn.AbstractSlot( slotSig = SynValSig ( synType = synType; attributes = attributes)) ->
978+ match traverseSynType path synType with
979+ | None -> attributeApplicationDives path attributes |> pick attributes
980+ | x -> x
926981 | SynMemberDefn.Interface ( interfaceType = synType; members = synMemberDefnsOption) ->
927982 match visitor.VisitInterfaceSynMemberDefnType( path, synType) with
928983 | None ->
@@ -963,13 +1018,20 @@ module SyntaxTraversal =
9631018 let path = SyntaxNode.SynBinding b :: origPath
9641019
9651020 match b with
966- | SynBinding ( headPat = synPat; expr = synExpr) ->
967- match traversePat path synPat with
968- | None -> traverseSynExpr path synExpr
969- | x -> x
1021+ | SynBinding ( headPat = synPat; expr = synExpr; attributes = attributes; range = m) ->
1022+ [
1023+ yield ! attributeApplicationDives path attributes
1024+ dive synPat synPat.Range ( traversePat path)
1025+ dive synExpr synExpr.Range ( traverseSynExpr path)
1026+ ]
1027+ |> pick m b
9701028
9711029 visitor.VisitBinding( origPath, defaultTraverse, b)
9721030
1031+ and attributeApplicationDives origPath attributes =
1032+ attributes
1033+ |> List.map ( fun attributes -> dive () attributes.Range ( fun () -> visitor.VisitAttributeApplication( origPath, attributes)))
1034+
9731035 match parseTree with
9741036 | ParsedInput.ImplFile file ->
9751037 let l = file.Contents
0 commit comments