-
Notifications
You must be signed in to change notification settings - Fork 830
Description
The ranges for modules and types in the parsed ast within signature files extend past the end of their scopes and overlap with the following constructs instead of stopping at the end of the last nested construct (where the ranges end in .fs files)
The AST for this sig file shows the issue -
namespace Microsoft.FSharp.Core
open System
open System.Collections.Generic
open Microsoft.FSharp.Core
open Microsoft.FSharp.Collections
open System.Collections
module Tuple =
type Tuple<'T1,'T2,'T3,'T4> =
interface IStructuralEquatable
interface IStructuralComparable
interface IComparable
new : 'T1 * 'T2 * 'T3 * 'T4 -> Tuple<'T1,'T2,'T3,'T4>
member Item1 : 'T1 with get
member Item2 : 'T2 with get
member Item3 : 'T3 with get
member Item4 : 'T4 with get
module Choice =
/// <summary>Helper types for active patterns with 6 choices.</summary>
[<StructuralEquality; StructuralComparison>]
[<CompiledName("FSharpChoice`6")>]
type Choice<'T1,'T2,'T3,'T4,'T5,'T6> =
/// <summary>Choice 1 of 6 choices</summary>
| Choice1Of6 of 'T1
/// <summary>Choice 2 of 6 choices</summary>
| Choice2Of6 of 'T2
/// <summary>Choice 3 of 6 choices</summary>
| Choice3Of6 of 'T3
/// <summary>Choice 4 of 6 choices</summary>
| Choice4Of6 of 'T4
/// <summary>Choice 5 of 6 choices</summary>
| Choice5Of6 of 'T5
/// <summary>Choice 6 of 6 choices</summary>
| Choice6Of6 of 'T6
/// <summary>Basic F# Operators. This module is automatically opened in all F# code.</summary>
[<AutoOpen>]
module Operators =
type ``[,]``<'T> with
[<CompiledName("Length1")>]
/// <summary>Get the length of an array in the first dimension </summary>
member Length1 : int
[<CompiledName("Length2")>]
/// <summary>Get the length of the array in the second dimension </summary>
member Length2 : int
[<CompiledName("Base1")>]
/// <summary>Get the lower bound of the array in the first dimension </summary>
member Base1 : int
[<CompiledName("Base2")>]
/// <summary>Get the lower bound of the array in the second dimension </summary>
member Base2 : intThe ends of the AST for module Tuple and type Tuple are
SigExample.fsi (13,8--23,6) IsSynthetic=false),[],
SigExample.fsi (13,8--23,6) IsSynthetic=false)],
SigExample.fsi (12,4--23,6) IsSynthetic=false)],
SigExample.fsi (10,0--23,6) IsSynthetic=false);
making it
module Tuple =
type Tuple<'T1,'T2,'T3,'T4> =
interface IStructuralEquatable
interface IStructuralComparable
interface IComparable
new : 'T1 * 'T2 * 'T3 * 'T4 -> Tuple<'T1,'T2,'T3,'T4>
member Item1 : 'T1 with get
member Item2 : 'T2 with get
member Item3 : 'T3 with get
member Item4 : 'T4 with get
moduleIt should end at SigExample.fsi (20,8--20,35)
The end of the module Choice AST is
SigExample.fsi (28,4--45,2) IsSynthetic=false)],
SigExample.fsi (23,0--45,2) IsSynthetic=false);
making it
module Choice =
/// <summary>Helper types for active patterns with 6 choices.</summary>
[<StructuralEquality; StructuralComparison>]
[<CompiledName("FSharpChoice`6")>]
type Choice<'T1,'T2,'T3,'T4,'T5,'T6> =
/// <summary>Choice 1 of 6 choices</summary>
| Choice1Of6 of 'T1
/// <summary>Choice 2 of 6 choices</summary>
| Choice2Of6 of 'T2
/// <summary>Choice 3 of 6 choices</summary>
| Choice3Of6 of 'T3
/// <summary>Choice 4 of 6 choices</summary>
| Choice4Of6 of 'T4
/// <summary>Choice 5 of 6 choices</summary>
| Choice5Of6 of 'T5
/// <summary>Choice 6 of 6 choices</summary>
| Choice6Of6 of 'T6
/// <summary>Basic F# Operators. This module is automatically opened in all F# code.</summary>
[<It should end at (SigExample.fsi (30,6--40,25))
I've included a repo setup using FSharp.Compiler.Service and the UAST traversal that was added for the block structure service, but I've commented out the logic that was necessary to restrict the ranges to their proper scope
from UAST.fs
let lastMemberSigRangeElse r memberSigs =
r
// match memberSigs with
// | [] -> r
// | ls ->
// match List.last ls with
// | SynMemberSig.Inherit (range=r)
// | SynMemberSig.Interface (range=r)
// | SynMemberSig.Member (range=r)
// | SynMemberSig.NestedType (range=r)
// | SynMemberSig.ValField (range=r) -> r
let lastTypeDefnSigRangeElse range (typeSigs:SynTypeDefnSig list) =
range
// match typeSigs with
// | [] -> range
// | ls ->
// let (SynTypeDefnSig.TypeDefnSig(_,_,memberSigs,r)) = List.last ls
// lastMemberSigRangeElse r memberSigs
let lastModuleSigDeclRangeElse range (sigDecls:SynModuleSigDecls) =
range
// match sigDecls with
// | [] -> range
// | ls -> match List.last ls with
// | SynModuleSigDecl.Types (typeSigs,r) -> lastTypeDefnSigRangeElse r typeSigs
// | SynModuleSigDecl.Val (ValSpfn(range=r),_) -> r
// | SynModuleSigDecl.Exception(_,r) -> r
// | SynModuleSigDecl.Open(_,r)-> r
// | SynModuleSigDecl.ModuleAbbrev(_,_,r)-> r
// | _ -> range
although this does prevent the print traversal from covering the entire tree for the print function in the included helper script
The repo includes sample files which can have their AST printed in FSI via TraverseAST.fsx
parsingError.zip
Expected behavior
UAST range stops and the end of the construct
Actual behavior
UAST range extends into or past the start of the next construct
Known workarounds
Modify the UAST traversal to get around faulty parse
- Branch - master HEAD