Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions src/fsharp/service/ServiceParseTreeWalk.fs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ type SyntaxVisitorBase<'T>() =
ignore (path, componentInfo, typeDefnKind, synType, members, range)
None

/// VisitRecordDefn allows overriding behavior when visiting record definitions (by default do nothing)
abstract VisitRecordDefn: path: SyntaxVisitorPath * fields: SynField list * range -> 'T option
default _.VisitRecordDefn(path, fields, range) =
ignore (path, fields, range)
None

/// VisitUnionDefn allows overriding behavior when visiting union definitions (by default do nothing)
abstract VisitUnionDefn: path: SyntaxVisitorPath * cases: SynUnionCase list * range -> 'T option
default _.VisitUnionDefn(path, cases, range) =
ignore (path, cases, range)
None

/// VisitEnumDefn allows overriding behavior when visiting enum definitions (by default do nothing)
abstract VisitEnumDefn: path: SyntaxVisitorPath * cases: SynEnumCase list * range -> 'T option
default _.VisitEnumDefn(path, cases, range) =
ignore (path, cases, range)
None

/// VisitInterfaceSynMemberDefnType allows overriding behavior for visiting interface member in types (by default - do nothing)
abstract VisitInterfaceSynMemberDefnType: path: SyntaxVisitorPath * synType: SynType -> 'T option
default _.VisitInterfaceSynMemberDefnType(path, synType) =
Expand Down Expand Up @@ -709,10 +727,16 @@ module SyntaxTraversal =
yield! synMemberDefns |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path traverseInherit
| SynTypeDefnRepr.Simple(synTypeDefnSimpleRepr, _range) ->
match synTypeDefnSimpleRepr with
| SynTypeDefnSimpleRepr.TypeAbbrev(_,synType,m) ->
yield dive synTypeDefnRepr synTypeDefnRepr.Range (fun _ -> visitor.VisitTypeAbbrev(path, synType,m))
| SynTypeDefnSimpleRepr.Record(_synAccessOption, fields, m) ->
yield dive () synTypeDefnRepr.Range (fun () -> visitor.VisitRecordDefn(path, fields, m))
| SynTypeDefnSimpleRepr.Union(_synAccessOption, cases, m) ->
yield dive () synTypeDefnRepr.Range (fun () -> visitor.VisitUnionDefn(path, cases, m))
| SynTypeDefnSimpleRepr.Enum(cases, m) ->
yield dive () synTypeDefnRepr.Range (fun () -> visitor.VisitEnumDefn(path, cases, m))
| SynTypeDefnSimpleRepr.TypeAbbrev(_, synType, m) ->
yield dive synTypeDefnRepr synTypeDefnRepr.Range (fun _ -> visitor.VisitTypeAbbrev(path, synType, m))
| _ ->
() // enums/DUs/record definitions don't have any SynExprs inside them
()
yield! synMemberDefns |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path (fun _ -> None)
] |> pick tRange tydef

Expand Down
9 changes: 9 additions & 0 deletions src/fsharp/service/ServiceParseTreeWalk.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ type SyntaxVisitorBase<'T> =
abstract VisitInheritSynMemberDefn: path: SyntaxVisitorPath * componentInfo: SynComponentInfo * typeDefnKind: SynTypeDefnKind * synType: SynType * members: SynMemberDefns * range: range -> 'T option
default VisitInheritSynMemberDefn: path: SyntaxVisitorPath * componentInfo: SynComponentInfo * typeDefnKind: SynTypeDefnKind * synType: SynType * members: SynMemberDefns * range: range -> 'T option

abstract VisitRecordDefn: path: SyntaxVisitorPath * fields: SynField list * range -> 'T option
default VisitRecordDefn: path: SyntaxVisitorPath * fields: SynField list * range -> 'T option

abstract VisitUnionDefn: path: SyntaxVisitorPath * cases: SynUnionCase list * range -> 'T option
default VisitUnionDefn: path: SyntaxVisitorPath * cases: SynUnionCase list * range -> 'T option

abstract VisitEnumDefn: path: SyntaxVisitorPath * cases: SynEnumCase list * range -> 'T option
default VisitEnumDefn: path: SyntaxVisitorPath * cases: SynEnumCase list * range -> 'T option

abstract VisitInterfaceSynMemberDefnType: path: SyntaxVisitorPath * synType: SynType -> 'T option
default VisitInterfaceSynMemberDefnType: path: SyntaxVisitorPath * synType: SynType -> 'T option

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8905,6 +8905,7 @@ FSharp.Compiler.Syntax.SyntaxTraversal: Microsoft.FSharp.Core.FSharpOption`1[T]
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitBinding(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynBinding,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynBinding)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitComponentInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynComponentInfo)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitEnumDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynEnumCase], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitExpr(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1[T]], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynExpr)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitHashDirective(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.ParsedHashDirective, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitImplicitInherit(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range)
Expand All @@ -8915,10 +8916,12 @@ FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOptio
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitModuleDecl(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynModuleDecl,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynModuleDecl)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitModuleOrNamespace(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynModuleOrNamespace)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitPat(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynPat,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynPat)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordField(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.LongIdentWithDots])
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynSimplePat])
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitType(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynType,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynType)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitTypeAbbrev(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitUnionDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynUnionCase], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Void .ctor()
FSharp.Compiler.Syntax.TyparStaticReq
FSharp.Compiler.Syntax.TyparStaticReq+Tags: Int32 HeadType
Expand Down
39 changes: 39 additions & 0 deletions tests/service/TreeVisitorTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,42 @@ let ``Visit type test`` () =

SyntaxTraversal.Traverse(mkPos 1 3, parseTree, visitor)
|> Option.iter (fun _ -> failwith "Should not visit type")

[<Test>]
let ``Visit record definition test`` () =
let visitor =
{ new SyntaxVisitorBase<_>() with
member x.VisitRecordDefn(_, fields, _) = Some fields }

let source = "type R = { A: int; B: string }"
let parseTree = parseSourceCode("C:\\test.fs", source)

match SyntaxTraversal.Traverse(pos0, parseTree, visitor) with
| Some [ SynField (_, _, Some id1, _, _, _, _, _); SynField (_, _, Some id2, _, _, _, _, _) ] when id1.idText = "A" && id2.idText = "B" -> ()
| _ -> failwith "Did not visit record definition"

[<Test>]
let ``Visit union definition test`` () =
let visitor =
{ new SyntaxVisitorBase<_>() with
member x.VisitUnionDefn(_, cases, _) = Some cases }

let source = "type U = A | B of string"
let parseTree = parseSourceCode("C:\\test.fs", source)

match SyntaxTraversal.Traverse(pos0, parseTree, visitor) with
| Some [ SynUnionCase (_, id1, _, _, _, _); SynUnionCase (_, id2, _, _, _, _) ] when id1.idText = "A" && id2.idText = "B" -> ()
| _ -> failwith "Did not visit union definition"

[<Test>]
let ``Visit enum definition test`` () =
let visitor =
{ new SyntaxVisitorBase<_>() with
member x.VisitEnumDefn(_, cases, _) = Some cases }

let source = "type E = A = 0 | B = 1"
let parseTree = parseSourceCode("C:\\test.fs", source)

match SyntaxTraversal.Traverse(pos0, parseTree, visitor) with
| Some [ SynEnumCase (_, id1, _, _, _, _); SynEnumCase (_, id2, _, _, _, _) ] when id1.idText = "A" && id2.idText = "B" -> ()
| _ -> failwith "Did not visit enum definition"