Skip to content

Parsed AST has incorrect ranges for Signature Files #2094

@cloudRoutine

Description

@cloudRoutine

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 : int

The 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


module

It 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-LangService-APIBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions