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
5 changes: 5 additions & 0 deletions src/Compiler/Checking/CheckPatterns.fs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,11 @@ and TcPat warnOnUpper (cenv: cenv) env valReprInfo vFlags (patEnv: TcPatLinearEn
| SynPat.Or (pat1, pat2, m, _) ->
TcPatOr warnOnUpper cenv env vFlags patEnv ty pat1 pat2 m

| SynPat.ListCons(pat1, pat2, m, trivia) ->
let longDotId = SynLongIdent((mkSynCaseName trivia.ColonColonRange opNameCons), [], [Some (FSharp.Compiler.SyntaxTrivia.IdentTrivia.OriginalNotation "::")])
let args = SynArgPats.Pats [ SynPat.Tuple(false, [ pat1; pat2 ], m) ]
TcPatLongIdent warnOnUpper cenv env ad valReprInfo vFlags patEnv ty (longDotId, None, args, None, m)

| SynPat.Ands (pats, m) ->
TcPatAnds warnOnUpper cenv env vFlags patEnv ty pats m

Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/Service/ServiceParseTreeWalk.fs
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,8 @@ module SyntaxTraversal =
match p with
| SynPat.Paren (p, _) -> traversePat path p
| SynPat.As (p1, p2, _)
| SynPat.Or (p1, p2, _, _) -> [ p1; p2 ] |> List.tryPick (traversePat path)
| SynPat.Or (p1, p2, _, _)
| SynPat.ListCons (p1, p2, _, _) -> [ p1; p2 ] |> List.tryPick (traversePat path)
| SynPat.Ands (ps, _)
| SynPat.Tuple (_, ps, _)
| SynPat.ArrayOrList (_, ps, _) -> ps |> List.tryPick (traversePat path)
Expand Down
6 changes: 4 additions & 2 deletions src/Compiler/Service/ServiceParsedInputOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,8 @@ module ParsedInput =
| SynPat.As (pat1, pat2, _) -> List.tryPick walkPat [ pat1; pat2 ]
| SynPat.Typed (pat, t, _) -> walkPat pat |> Option.orElseWith (fun () -> walkType t)
| SynPat.Attrib (pat, Attributes attrs, _) -> walkPat pat |> Option.orElseWith (fun () -> List.tryPick walkAttribute attrs)
| SynPat.Or (pat1, pat2, _, _) -> List.tryPick walkPat [ pat1; pat2 ]
| SynPat.Or (pat1, pat2, _, _)
| SynPat.ListCons (pat1, pat2, _, _) -> List.tryPick walkPat [ pat1; pat2 ]
| SynPat.LongIdent (typarDecls = typars; argPats = ConstructorPats pats; range = r) ->
ifPosInRange r (fun _ -> kind)
|> Option.orElseWith (fun () ->
Expand Down Expand Up @@ -1638,7 +1639,8 @@ module ParsedInput =
walkPat pat
List.iter walkAttribute attrs
| SynPat.As (pat1, pat2, _)
| SynPat.Or (pat1, pat2, _, _) -> List.iter walkPat [ pat1; pat2 ]
| SynPat.Or (pat1, pat2, _, _)
| SynPat.ListCons (pat1, pat2, _, _) -> List.iter walkPat [ pat1; pat2 ]
| SynPat.LongIdent (longDotId = ident; typarDecls = typars; argPats = ConstructorPats pats) ->
addLongIdentWithDots ident

Expand Down
1 change: 1 addition & 0 deletions src/Compiler/Service/ServiceXmlDocParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module XmlDocParsing =
| SynPat.Typed (pat, _type, _range) -> digNamesFrom pat
| SynPat.Attrib (pat, _attrs, _range) -> digNamesFrom pat
| SynPat.LongIdent(argPats = ConstructorPats pats) -> pats |> List.collect digNamesFrom
| SynPat.ListCons (p1, p2, _, _) -> List.collect digNamesFrom [ p1; p2 ]
| SynPat.Tuple (_, pats, _range) -> pats |> List.collect digNamesFrom
| SynPat.Paren (pat, _range) -> digNamesFrom pat
| SynPat.OptionalVal (id, _) -> [ id.idText ]
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,8 @@ type SynPat =

| Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia

| ListCons of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatListConsTrivia

| Ands of pats: SynPat list * range: range

| As of lhsPat: SynPat * rhsPat: SynPat * range: range
Expand Down Expand Up @@ -953,6 +955,7 @@ type SynPat =
| SynPat.Wild (range = m)
| SynPat.Named (range = m)
| SynPat.Or (range = m)
| SynPat.ListCons (range = m)
| SynPat.Ands (range = m)
| SynPat.As (range = m)
| SynPat.LongIdent (range = m)
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,9 @@ type SynPat =
/// A disjunctive pattern 'pat1 | pat2'
| Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia

/// A conjunctive pattern 'pat1 :: pat2'
| ListCons of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatListConsTrivia

/// A conjunctive pattern 'pat1 & pat2'
| Ands of pats: SynPat list * range: range

Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ type SynUnionCaseTrivia = { BarRange: range option }
[<NoEquality; NoComparison>]
type SynPatOrTrivia = { BarRange: range }

[<NoEquality; NoComparison>]
type SynPatListConsTrivia = { ColonColonRange: range }

[<NoEquality; NoComparison>]
type SynTypeDefnTrivia =
{
Expand Down
8 changes: 8 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,14 @@ type SynPatOrTrivia =
BarRange: range
}

/// Represents additional information for SynPat.Cons
[<NoEquality; NoComparison>]
type SynPatListConsTrivia =
{
/// The syntax range of the `::` token.
ColonColonRange: range
}

/// Represents additional information for SynTypeDefn
[<NoEquality; NoComparison>]
type SynTypeDefnTrivia =
Expand Down
6 changes: 4 additions & 2 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -3124,7 +3124,8 @@ headBindingPattern:
SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) }

| headBindingPattern COLON_COLON headBindingPattern
{ SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, SynArgPats.Pats [SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3)], None, lhs parseState) }
{ let mColonColon = rhs parseState 2
SynPat.ListCons($1, $3, rhs2 parseState 1 3, { ColonColonRange = mColonColon }) }

| tuplePatternElements %prec pat_tuple
{ let pats = normalizeTuplePat $1
Expand Down Expand Up @@ -3398,7 +3399,8 @@ parenPattern:
SynPat.Attrib($2, $1, mLhs) }

| parenPattern COLON_COLON parenPattern
{ SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, SynArgPats.Pats [ SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3) ], None, lhs parseState) }
{ let mColonColon = rhs parseState 2
SynPat.ListCons($1, $3, rhs2 parseState 1 3, { ColonColonRange = mColonColon }) }

| constrPattern { $1 }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8004,6 +8004,14 @@ FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Syntax.SynType get_pat()
FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Syntax.SynType pat
FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Text.Range get_range()
FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Text.Range range
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat get_lhsPat()
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat get_rhsPat()
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat lhsPat
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat rhsPat
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia get_trivia()
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia trivia
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Text.Range get_range()
FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Text.Range range
FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Syntax.SynArgPats argPats
FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Syntax.SynArgPats get_argPats()
FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Syntax.SynLongIdent get_longDotId()
Expand Down Expand Up @@ -8059,6 +8067,7 @@ FSharp.Compiler.Syntax.SynPat+Tags: Int32 DeprecatedCharRange
FSharp.Compiler.Syntax.SynPat+Tags: Int32 FromParseError
FSharp.Compiler.Syntax.SynPat+Tags: Int32 InstanceMember
FSharp.Compiler.Syntax.SynPat+Tags: Int32 IsInst
FSharp.Compiler.Syntax.SynPat+Tags: Int32 ListCons
FSharp.Compiler.Syntax.SynPat+Tags: Int32 LongIdent
FSharp.Compiler.Syntax.SynPat+Tags: Int32 Named
FSharp.Compiler.Syntax.SynPat+Tags: Int32 Null
Expand Down Expand Up @@ -8093,6 +8102,7 @@ FSharp.Compiler.Syntax.SynPat: Boolean IsDeprecatedCharRange
FSharp.Compiler.Syntax.SynPat: Boolean IsFromParseError
FSharp.Compiler.Syntax.SynPat: Boolean IsInstanceMember
FSharp.Compiler.Syntax.SynPat: Boolean IsIsInst
FSharp.Compiler.Syntax.SynPat: Boolean IsListCons
FSharp.Compiler.Syntax.SynPat: Boolean IsLongIdent
FSharp.Compiler.Syntax.SynPat: Boolean IsNamed
FSharp.Compiler.Syntax.SynPat: Boolean IsNull
Expand All @@ -8113,6 +8123,7 @@ FSharp.Compiler.Syntax.SynPat: Boolean get_IsDeprecatedCharRange()
FSharp.Compiler.Syntax.SynPat: Boolean get_IsFromParseError()
FSharp.Compiler.Syntax.SynPat: Boolean get_IsInstanceMember()
FSharp.Compiler.Syntax.SynPat: Boolean get_IsIsInst()
FSharp.Compiler.Syntax.SynPat: Boolean get_IsListCons()
FSharp.Compiler.Syntax.SynPat: Boolean get_IsLongIdent()
FSharp.Compiler.Syntax.SynPat: Boolean get_IsNamed()
FSharp.Compiler.Syntax.SynPat: Boolean get_IsNull()
Expand All @@ -8133,6 +8144,7 @@ FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewDeprecatedCharRa
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewFromParseError(FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewInstanceMember(FSharp.Compiler.Syntax.Ident, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewIsInst(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewListCons(FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia)
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewLongIdent(FSharp.Compiler.Syntax.SynLongIdent, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynValTyparDecls], FSharp.Compiler.Syntax.SynArgPats, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewNamed(FSharp.Compiler.Syntax.SynIdent, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewNull(FSharp.Compiler.Text.Range)
Expand All @@ -8153,6 +8165,7 @@ FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+DeprecatedCharRange
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+FromParseError
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+InstanceMember
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+IsInst
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+ListCons
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+LongIdent
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+Named
FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+Null
Expand Down Expand Up @@ -9556,6 +9569,11 @@ FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: Microsoft.FShar
FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_ModuleKeyword()
FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: System.String ToString()
FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia
FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: FSharp.Compiler.Text.Range ColonColonRange
FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: FSharp.Compiler.Text.Range get_ColonColonRange()
FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: System.String ToString()
FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: Void .ctor(FSharp.Compiler.Text.Range)
FSharp.Compiler.SyntaxTrivia.SynPatOrTrivia
FSharp.Compiler.SyntaxTrivia.SynPatOrTrivia: FSharp.Compiler.Text.Range BarRange
FSharp.Compiler.SyntaxTrivia.SynPatOrTrivia: FSharp.Compiler.Text.Range get_BarRange()
Expand Down
24 changes: 20 additions & 4 deletions tests/service/SyntaxTreeTests/PatternTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ let (head::tail) = [ 1;2;4]
match parseResults with
| ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [
SynModuleDecl.Let(
bindings = [ SynBinding(headPat = SynPat.Paren(SynPat.LongIdent(longDotId = SynLongIdent([ opColonColonIdent ], _, [ Some (IdentTrivia.OriginalNotation "::") ])), _)) ]
bindings = [ SynBinding(headPat = SynPat.Paren(pat = SynPat.ListCons(trivia = trivia))) ]
)
]) ])) ->
Assert.AreEqual("op_ColonColon", opColonColonIdent.idText)
assertRange (2,9) (2,11) trivia.ColonColonRange
| _ -> Assert.Fail $"Could not get valid AST, got {parseResults}"

[<Test>]
Expand All @@ -92,11 +92,11 @@ match x with
| ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [
SynModuleDecl.Expr(
expr = SynExpr.Match(clauses = [
SynMatchClause(pat = SynPat.LongIdent(longDotId = SynLongIdent([ opColonColonIdent ], _, [ Some (IdentTrivia.OriginalNotation "::") ])))
SynMatchClause(pat = SynPat.ListCons(trivia = trivia))
])
)
]) ])) ->
Assert.AreEqual("op_ColonColon", opColonColonIdent.idText)
assertRange (3, 9) (3, 11) trivia.ColonColonRange
| _ -> Assert.Fail $"Could not get valid AST, got {parseResults}"

[<Test>]
Expand All @@ -122,3 +122,19 @@ match data with
]) ])) ->
assertRange (3, 13) (5, 13) trivia.ParenRange
| _ -> Assert.Fail $"Could not get valid AST, got {parseResults}"

[<Test>]
let ``:: in head pattern`` () =
let parseResults =
getParseResults
"""
let 1 :: _ = [ 4; 5; 6 ]
"""

match parseResults with
| ParsedInput.ImplFile(ParsedImplFileInput(contents = [ SynModuleOrNamespace(decls = [
SynModuleDecl.Let(bindings = [ SynBinding(headPat =
SynPat.ListCons(trivia = trivia)) ])
]) ])) ->
assertRange (2,6) (2, 8) trivia.ColonColonRange
| _ -> Assert.Fail $"Could not get valid AST, got {parseResults}"