diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 1e9c0418a1..238e3668de 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -471,13 +471,13 @@ and TcNullPat cenv env patEnv ty m = and CheckNoArgsForLiteral args m = match args with | SynArgPats.Pats [] - | SynArgPats.NamePatPairs ([], _) -> () + | SynArgPats.NamePatPairs (pats = []) -> () | _ -> errorR (Error (FSComp.SR.tcLiteralDoesNotTakeArguments (), m)) and GetSynArgPatterns args = match args with | SynArgPats.Pats args -> args - | SynArgPats.NamePatPairs (pairs, _) -> List.map (fun (_, _, pat) -> pat) pairs + | SynArgPats.NamePatPairs (pats = pairs) -> List.map (fun (_, _, pat) -> pat) pairs and TcArgPats warnOnUpper (cenv: cenv) env vFlags patEnv args = let g = cenv.g @@ -600,7 +600,7 @@ and TcPatLongIdentUnionCaseOrExnCase warnOnUpper cenv env ad vFlags patEnv ty (m let args, extraPatternsFromNames = match args with | SynArgPats.Pats args -> args, [] - | SynArgPats.NamePatPairs (pairs, m) -> + | SynArgPats.NamePatPairs (pairs, m, _) -> // rewrite patterns from the form (name-N = pat-N; ...) to (..._, pat-N, _...) // so type T = Case of name: int * value: int // | Case(value = v) diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index 08c89d969f..c75b133a37 100755 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -797,7 +797,7 @@ module SyntaxTraversal = | SynPat.LongIdent (argPats = args) -> match args with | SynArgPats.Pats ps -> ps |> List.tryPick (traversePat path) - | SynArgPats.NamePatPairs (ps, _) -> ps |> List.map (fun (_, _, pat) -> pat) |> List.tryPick (traversePat path) + | SynArgPats.NamePatPairs (pats = ps) -> ps |> List.map (fun (_, _, pat) -> pat) |> List.tryPick (traversePat path) | SynPat.Typed (p, ty, _) -> match traversePat path p with | None -> traverseSynType path ty diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index 6b6a1c906f..ab24bcb5a4 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -556,7 +556,7 @@ module ParsedInput = let (|ConstructorPats|) pats = match pats with | SynArgPats.Pats ps -> ps - | SynArgPats.NamePatPairs (xs, _) -> List.map (fun (_, _, pat) -> pat) xs + | SynArgPats.NamePatPairs (pats = xs) -> List.map (fun (_, _, pat) -> pat) xs /// A recursive pattern that collect all sequential expressions to avoid StackOverflowException let rec (|Sequentials|_|) expr = @@ -1566,7 +1566,7 @@ module ParsedInput = let (|ConstructorPats|) pats = match pats with | SynArgPats.Pats ps -> ps - | SynArgPats.NamePatPairs (xs, _) -> List.map (fun (_, _, pat) -> pat) xs + | SynArgPats.NamePatPairs (pats = xs) -> List.map (fun (_, _, pat) -> pat) xs /// Returns all `Ident`s and `LongIdent`s found in an untyped AST. let getLongIdents (parsedInput: ParsedInput) : IDictionary = diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 1845f46354..11c0c28375 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -886,12 +886,12 @@ type SynSimplePats = type SynArgPats = | Pats of pats: SynPat list - | NamePatPairs of pats: (Ident * range * SynPat) list * range: range + | NamePatPairs of pats: (Ident * range * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia member x.Patterns = match x with | Pats pats -> pats - | NamePatPairs (pats, _) -> pats |> List.map (fun (_, _, pat) -> pat) + | NamePatPairs (pats = pats) -> pats |> List.map (fun (_, _, pat) -> pat) [] type SynPat = diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index b1538eaa48..2a34ba55c4 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -1024,7 +1024,7 @@ type SynSimplePats = type SynArgPats = | Pats of pats: SynPat list - | NamePatPairs of pats: (Ident * range * SynPat) list * range: range + | NamePatPairs of pats: (Ident * range * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia member Patterns: SynPat list diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs index 1b03d20b61..5f500caec8 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs @@ -257,3 +257,6 @@ type SynMemberGetSetTrivia = AndKeyword: range option SetKeyword: range option } + +[] +type SynArgPatsNamePatPairsTrivia = { ParenRange: range } diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi index fbdf8ecf30..3cac74f902 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi @@ -365,3 +365,11 @@ type SynMemberGetSetTrivia = /// The syntax range of the `set` keyword SetKeyword: range option } + +/// Represents additional information for SynArgPats.NamePatPairs +[] +type SynArgPatsNamePatPairsTrivia = + { + /// The syntax range from the beginning of the `(` token till the end of the `)` token. + ParenRange: range + } diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 6e19467801..63dba4eb2c 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3237,7 +3237,10 @@ constrPattern: atomicPatsOrNamePatPairs: | LPAREN namePatPairs rparen - { SynArgPats.NamePatPairs $2, snd $2 } + { let mParen = rhs2 parseState 1 3 + let pats, m = $2 + let trivia = { ParenRange = mParen } + SynArgPats.NamePatPairs(pats, m, trivia), snd $2 } | atomicPatterns { let mParsed = rhs parseState 1 diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 736193358e..1eeb9b8bc9 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -5830,6 +5830,8 @@ FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Core.FSharpOption`1[FSharp.C FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] ident FSharp.Compiler.Syntax.SynArgInfo: System.String ToString() FSharp.Compiler.Syntax.SynArgPats +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia get_trivia() +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia trivia FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]] get_pats() @@ -5842,7 +5844,7 @@ FSharp.Compiler.Syntax.SynArgPats: Boolean IsNamePatPairs FSharp.Compiler.Syntax.SynArgPats: Boolean IsPats FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsNamePatPairs() FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsPats() -FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewPats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat]) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+NamePatPairs FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+Pats @@ -9396,6 +9398,11 @@ FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: Microsoft.FSharp.Collecti FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTrivia.ConditionalDirectiveTrivia] get_ConditionalDirectives() FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: System.String ToString() FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTrivia.ConditionalDirectiveTrivia], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTrivia.CommentTrivia]) +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: FSharp.Compiler.Text.Range ParenRange +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: FSharp.Compiler.Text.Range get_ParenRange() +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: Void .ctor(FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTrivia.SynBindingTrivia FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia Zero FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia get_Zero() diff --git a/tests/service/SyntaxTreeTests/PatternTests.fs b/tests/service/SyntaxTreeTests/PatternTests.fs index 61a511dc88..72b10da779 100644 --- a/tests/service/SyntaxTreeTests/PatternTests.fs +++ b/tests/service/SyntaxTreeTests/PatternTests.fs @@ -97,4 +97,28 @@ match x with ) ]) ])) -> Assert.AreEqual("op_ColonColon", opColonColonIdent.idText) - | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" \ No newline at end of file + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" + +[] +let ``Parentheses of SynArgPats.NamePatPairs`` () = + let parseResults = + getParseResults + """ +match data with +| OnePartData( // foo + part1 = p1 + (* bar *) ) -> p1 +| _ -> failwith "todo" +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Expr( + expr = SynExpr.Match(clauses = [ + SynMatchClause(pat = SynPat.LongIdent(argPats = SynArgPats.NamePatPairs(trivia = trivia))) + _ + ]) + ) + ]) ])) -> + assertRange (3, 13) (5, 13) trivia.ParenRange + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}"