Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 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
2 changes: 1 addition & 1 deletion src/fsharp/CompilerDiagnostics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ let OutputPhasedErrorR (os: StringBuilder) (err: PhasedDiagnostic) (canSuggestNa
printfn " ----"
//printfn " state %d" state
for rp in rps do
printfn " non-terminal %+A: ... " (Parser.prodIdxToNonTerminal rp)
printfn " non-terminal %+A (idx %d): ... " (Parser.prodIdxToNonTerminal rp) rp
#endif

match ctxt.CurrentToken with
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,11 @@ type SynArgPats =
pats: (Ident * SynPat) list *
range: range

member x.Patterns =
match x with
| Pats pats -> pats
| NamePatPairs (pats, _) -> pats |> List.map snd

[<NoEquality; NoComparison;RequireQualifiedAccess>]
type SynPat =

Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/SyntaxTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,8 @@ type SynArgPats =
pats: (Ident * SynPat) list *
range: range

member Patterns: SynPat list

/// Represents a syntax tree for an F# pattern
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynPat =
Expand Down
78 changes: 53 additions & 25 deletions src/fsharp/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ let rangeOfLongIdent(lid:LongIdent) =
%type <Ident> ident
%type <SynType> typ typEOF
%type <SynTypeDefnSig list> tyconSpfnList
%type <SynArgPats * Range> atomicPatsOrNamePatPairs
%type <SynPat list> atomicPatterns
%type <Range * SynExpr> patternResult
%type <SynExpr> declExpr
%type <SynExpr> minusExpr
Expand Down Expand Up @@ -2337,13 +2339,6 @@ opt_explicitValTyparDecls:
|
{ SynValTyparDecls(None, true) }

opt_explicitValTyparDecls2:
| explicitValTyparDecls
{ Some $1 }

| /* EMPTY */
{ None }

/* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */
/* See the F# specification "Lexical analysis of type applications and type parameter definitions" */
opt_typeConstraints:
Expand Down Expand Up @@ -3103,17 +3098,45 @@ namePatPair:
{ ($1, $3) }

constrPattern:
| atomicPatternLongIdent explicitValTyparDecls
{ let vis, lid = $1 in SynPat.LongIdent (lid, None, Some $2, SynArgPats.Pats [], vis, lhs parseState) }

| atomicPatternLongIdent opt_explicitValTyparDecls2 atomicPatsOrNamePatPairs %prec pat_app
{ let vis, lid = $1 in SynPat.LongIdent (lid, None, $2, $3, vis, lhs parseState) }

| atomicPatternLongIdent opt_explicitValTyparDecls2 HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs
{ let vis, lid = $1 in SynPat.LongIdent (lid, None, $2, $4, vis, lhs parseState) }

| atomicPatternLongIdent opt_explicitValTyparDecls2 HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs
{ let vis, lid = $1 in SynPat.LongIdent (lid, None, $2, $4, vis, lhs parseState) }
| atomicPatternLongIdent explicitValTyparDecls
{ let vis, lid = $1
SynPat.LongIdent (lid, None, Some $2, SynArgPats.Pats [], vis, lhs parseState) }

| atomicPatternLongIdent explicitValTyparDecls atomicPatsOrNamePatPairs %prec pat_app
{ let vis, lid = $1
let args, argsM = $3
let m = unionRanges (rhs2 parseState 1 2) argsM
SynPat.LongIdent (lid, None, Some $2, args, vis, m) }

| atomicPatternLongIdent explicitValTyparDecls HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs
{ let vis, lid = $1
let args, argsM = $4
let m = unionRanges (rhs2 parseState 1 2) argsM
SynPat.LongIdent (lid, None, Some $2, args, vis, m) }

| atomicPatternLongIdent explicitValTyparDecls HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs
{ let vis, lid = $1
let args, argsM = $4
let m = unionRanges (rhs2 parseState 1 2) argsM
SynPat.LongIdent (lid, None, Some $2, args, vis, m) }

| atomicPatternLongIdent atomicPatsOrNamePatPairs %prec pat_app
{ let vis, lid = $1
let args, argsM = $2
let m = unionRanges (rhs parseState 1) argsM
SynPat.LongIdent (lid, None, None, args, vis, m) }

| atomicPatternLongIdent HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs
{ let vis, lid = $1
let args, argsM = $3
let m = unionRanges (rhs parseState 1) argsM
SynPat.LongIdent (lid, None, None, args, vis, m) }

| atomicPatternLongIdent HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs
{ let vis, lid = $1
let args, argsM = $3
let m = unionRanges (rhs parseState 1) argsM
SynPat.LongIdent (lid, None, None, args, vis, m) }

| COLON_QMARK atomTypeOrAnonRecdType %prec pat_isinst
{ SynPat.IsInst($2, lhs parseState) }
Expand All @@ -3123,10 +3146,12 @@ constrPattern:

atomicPatsOrNamePatPairs:
| LPAREN namePatPairs rparen
{ SynArgPats.NamePatPairs $2 }
{ SynArgPats.NamePatPairs $2, snd $2 }

| atomicPatterns
{ SynArgPats.Pats $1 }
{ let mWhole = rhs parseState 1
let m = (mWhole.StartRange, $1) ||> unionRangeWithListBy (fun p -> p.Range)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe call this mAll

SynArgPats.Pats $1, m }

atomicPatterns:
| atomicPattern atomicPatterns %prec pat_args
Expand Down Expand Up @@ -3970,6 +3995,12 @@ patternClauses:
let m = unionRanges resultExpr.Range patm
(SynMatchClause(pat, guard, (Some mArrow), resultExpr, m, DebugPointAtTarget.Yes) :: clauses), mLast }

| patternAndGuard error BAR patternClauses
{ let pat, guard, patm = $1
let clauses, mLast = $4
let m = guard |> Option.map (fun e -> unionRanges patm e.Range) |> Option.defaultValue patm
(SynMatchClause(pat, guard, None, arbExpr ("patternClauses1", m.EndRange), m, DebugPointAtTarget.Yes) :: clauses), mLast }

| patternAndGuard patternResult BAR error
{ let pat, guard, patm = $1
let mArrow, resultExpr = $2
Expand All @@ -3989,12 +4020,9 @@ patternClauses:
| patternAndGuard error
{ let pat, guard, patm = $1
let mLast = rhs parseState 2
let m =
match guard with
| Some e -> unionRanges patm e.Range
| _ -> patm
let m = guard |> Option.map (fun e -> unionRanges patm e.Range) |> Option.defaultValue patm
// silent recovery
[SynMatchClause(pat, guard, None, SynExpr.Const (SynConst.Unit, mLast.EndRange), m, DebugPointAtTarget.Yes)], mLast }
[SynMatchClause(pat, guard, None, arbExpr ("patternClauses2", m.EndRange), m, DebugPointAtTarget.Yes)], mLast }

patternGuard:
| WHEN declExpr
Expand Down
11 changes: 9 additions & 2 deletions src/fsharp/service/ServiceParsedInputOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,11 @@ module ParsedInput =
if isOnTheRightOfComma elements commas e then Some args else None
| _ -> None

let (|SkipFromParseErrorPat|) pat =
match pat with
| SynPat.FromParseError(pat, _) -> pat
| _ -> pat

let walker =
{
new SyntaxVisitorBase<_>() with
Expand Down Expand Up @@ -980,7 +985,8 @@ module ParsedInput =

member _.VisitBinding(_path, defaultTraverse, (SynBinding(headPat = headPat) as synBinding)) =

let visitParam = function
let visitParam (SkipFromParseErrorPat pat) =
match pat with
| SynPat.Named (range = range)
| SynPat.As (_, SynPat.Named (range = range), _) when rangeContainsPos range pos ->
// parameter without type hint, no completion
Expand All @@ -999,12 +1005,13 @@ module ParsedInput =
| SynArgPats.Pats pats ->
pats |> List.tryPick (fun pat ->
match pat with
| SynPat.FromParseError(pat, _)
| SynPat.Paren(pat, _) ->
match pat with
| SynPat.Tuple(_, pats, _) ->
pats |> List.tryPick visitParam
| _ -> visitParam pat
| SynPat.Wild range when rangeContainsPos range pos ->
| SynPat.Wild range | SynPat.FromParseError (SynPat.Named _, range) when rangeContainsPos range pos ->
// let foo (x|
Some CompletionContext.Invalid
| _ -> visitParam pat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5239,6 +5239,29 @@ FSharp.Compiler.Syntax.DebugPointAtSwitch: Int32 GetHashCode(System.Collections.
FSharp.Compiler.Syntax.DebugPointAtSwitch: Int32 Tag
FSharp.Compiler.Syntax.DebugPointAtSwitch: Int32 get_Tag()
FSharp.Compiler.Syntax.DebugPointAtSwitch: System.String ToString()
FSharp.Compiler.Syntax.DebugPointAtTarget
FSharp.Compiler.Syntax.DebugPointAtTarget+Tags: Int32 No
FSharp.Compiler.Syntax.DebugPointAtTarget+Tags: Int32 Yes
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean Equals(FSharp.Compiler.Syntax.DebugPointAtTarget)
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean Equals(System.Object)
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean IsNo
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean IsYes
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean get_IsNo()
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean get_IsYes()
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget No
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget Yes
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget get_No()
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget get_Yes()
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget+Tags
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 CompareTo(FSharp.Compiler.Syntax.DebugPointAtTarget)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 CompareTo(System.Object)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 CompareTo(System.Object, System.Collections.IComparer)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 GetHashCode()
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 GetHashCode(System.Collections.IEqualityComparer)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 Tag
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 get_Tag()
FSharp.Compiler.Syntax.DebugPointAtTarget: System.String ToString()
FSharp.Compiler.Syntax.DebugPointAtTry
FSharp.Compiler.Syntax.DebugPointAtTry+Tags: Int32 Body
FSharp.Compiler.Syntax.DebugPointAtTry+Tags: Int32 No
Expand Down Expand Up @@ -5310,29 +5333,6 @@ FSharp.Compiler.Syntax.DebugPointAtWith: Int32 GetHashCode(System.Collections.IE
FSharp.Compiler.Syntax.DebugPointAtWith: Int32 Tag
FSharp.Compiler.Syntax.DebugPointAtWith: Int32 get_Tag()
FSharp.Compiler.Syntax.DebugPointAtWith: System.String ToString()
FSharp.Compiler.Syntax.DebugPointAtTarget
FSharp.Compiler.Syntax.DebugPointAtTarget+Tags: Int32 No
FSharp.Compiler.Syntax.DebugPointAtTarget+Tags: Int32 Yes
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean Equals(FSharp.Compiler.Syntax.DebugPointAtTarget)
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean Equals(System.Object)
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean IsNo
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean IsYes
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean get_IsNo()
FSharp.Compiler.Syntax.DebugPointAtTarget: Boolean get_IsYes()
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget No
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget Yes
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget get_No()
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget get_Yes()
FSharp.Compiler.Syntax.DebugPointAtTarget: FSharp.Compiler.Syntax.DebugPointAtTarget+Tags
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 CompareTo(FSharp.Compiler.Syntax.DebugPointAtTarget)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 CompareTo(System.Object)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 CompareTo(System.Object, System.Collections.IComparer)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 GetHashCode()
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 GetHashCode(System.Collections.IEqualityComparer)
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 Tag
FSharp.Compiler.Syntax.DebugPointAtTarget: Int32 get_Tag()
FSharp.Compiler.Syntax.DebugPointAtTarget: System.String ToString()
FSharp.Compiler.Syntax.ExprAtomicFlag
FSharp.Compiler.Syntax.ExprAtomicFlag: FSharp.Compiler.Syntax.ExprAtomicFlag Atomic
FSharp.Compiler.Syntax.ExprAtomicFlag: FSharp.Compiler.Syntax.ExprAtomicFlag NonAtomic
Expand Down Expand Up @@ -5728,6 +5728,8 @@ FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+Pats
FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+Tags
FSharp.Compiler.Syntax.SynArgPats: Int32 Tag
FSharp.Compiler.Syntax.SynArgPats: Int32 get_Tag()
FSharp.Compiler.Syntax.SynArgPats: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat] Patterns
FSharp.Compiler.Syntax.SynArgPats: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat] get_Patterns()
FSharp.Compiler.Syntax.SynArgPats: System.String ToString()
FSharp.Compiler.Syntax.SynAttribute
FSharp.Compiler.Syntax.SynAttribute: Boolean AppliesToGetterAndSetter
Expand Down
2 changes: 1 addition & 1 deletion tests/fsharp/typecheck/sigs/neg104.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ neg104.fs(20,23,20,24): parse error FS0010: Incomplete structured construct at o

neg104.fs(23,25,23,26): parse error FS0010: Incomplete structured construct at or before this point in expression

neg104.fs(26,28,26,29): parse error FS0010: Incomplete structured construct at or before this point in pattern
neg104.fs(26,28,26,29): parse error FS0010: Incomplete structured construct at or before this point in pattern matching. Expected '->' or other token.

neg104.fs(29,31,29,32): parse error FS0010: Incomplete structured construct at or before this point in pattern matching

Expand Down
4 changes: 1 addition & 3 deletions tests/fsharp/typecheck/sigs/neg104.vsbsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ neg104.fs(20,23,20,24): parse error FS0010: Incomplete structured construct at o

neg104.fs(23,25,23,26): parse error FS0010: Incomplete structured construct at or before this point in expression

neg104.fs(26,28,26,29): parse error FS0010: Incomplete structured construct at or before this point in pattern
neg104.fs(26,28,26,29): parse error FS0010: Incomplete structured construct at or before this point in pattern matching. Expected '->' or other token.

neg104.fs(29,31,29,32): parse error FS0010: Incomplete structured construct at or before this point in pattern matching

Expand All @@ -27,8 +27,6 @@ neg104.fs(20,9,20,22): typecheck error FS0025: Incomplete pattern matches on thi

neg104.fs(23,9,23,22): typecheck error FS0025: Incomplete pattern matches on this expression.

neg104.fs(26,9,26,22): typecheck error FS0025: Incomplete pattern matches on this expression.

neg104.fs(32,21,32,26): typecheck error FS0003: This value is not a function and cannot be applied.

neg104.fs(35,9,35,18): typecheck error FS0748: This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'.
4 changes: 0 additions & 4 deletions tests/fsharp/typecheck/sigs/neg80.vsbsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,3 @@
neg80.fsx(79,5,79,6): parse error FS0010: Unexpected symbol '|' in pattern matching

neg80.fsx(79,5,79,6): parse error FS0010: Unexpected symbol '|' in pattern matching

neg80.fsx(79,6,79,6): typecheck error FS0001: All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is 'string'. This branch returns a value of type 'unit'.

neg80.fsx(76,11,76,13): typecheck error FS0025: Incomplete pattern matches on this expression. For example, the value 'Horizontal (_, _)' may indicate a case not covered by the pattern(s).
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#light

//<Expects id="FS0010" status="error">Unexpected keyword 'type' in binding</Expects>
//<Expects id="FS0010" status="error">Unexpected keyword 'class' in pattern</Expects>
//<Expects id="FS0010" status="error">Unexpected keyword 'class' in binding. Expected '=' or other token.</Expects>

let type = 2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
// Regression test for FSHARP1.0:1525
// type constraints on pattern matching are deprecated and are now errors (used to be warnings)
// As of Beta2, we are not even giving the deprecation error.
//<Expects id="FS0010" span="(20,8-20,10)" status="error">Unexpected symbol ':>' in pattern$</Expects>
//<Expects id="FS0583" span="(20,5-20,6)" status="error">Unmatched '\('$</Expects>
//<Expects id="FS0010" span="(21,8-21,10)" status="error">Unexpected symbol ':>' in pattern. Expected '\)' or other token.</Expects>
//<Expects id="FS0583" span="(21,5-21,6)" status="error">Unmatched '\('$</Expects>
//<Expects id="FS0222" span="(8,1-9,1)" status="error">Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'. Only the last source file of an application may omit such a declaration.</Expects>
type A() = class
end

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// #Regression #Diagnostics
// Regression test for FSHARP1.0:2099
// Regression test for FSHARP1.0:2670
//<Expects id="FS0010" span="(18,50-18,52)" status="error">Unexpected symbol '<-' in pattern</Expects>
//<Expects id="FS0010" span="(18,50-18,52)" status="error">Unexpected symbol '<-' in binding. Expected '=' or other token.</Expects>
//<Expects id="FS0588" span="(18,42-18,45)" status="error">The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.</Expects>
//<Expects status="notin">lambda</Expects>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// #Regression #NoMT #FSI
// Regression test for FSHARP1.0:5629
//<Expects status="error" span="(4,6)" id="FS0010">Incomplete structured construct at or before this point in pattern$</Expects>
//<Expects status="error" span="(4,6)" id="FS0010">Incomplete structured construct at or before this point in binding. Expected '=' or other token.</Expects>
let f;;
exit 1;;
13 changes: 13 additions & 0 deletions tests/service/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,19 @@ let getSingleModuleLikeDecl (input: ParsedInput) =
| ParsedInput.ImplFile (ParsedImplFileInput (modules = [ decl ])) -> decl
| _ -> failwith "Could not get module decls"

let getSingleModuleMemberDecls (input: ParsedInput) =
match getSingleModuleLikeDecl input with
| SynModuleOrNamespace (decls = decls) -> decls

let getSingleExprInModule (input: ParsedInput) =
match getSingleModuleLikeDecl input with
| SynModuleOrNamespace (decls = decls) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would normally use

let (SynModuleOrNamespace (decls = decls)) = getSingleModuleLikeDecl input

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not call getSingleModuleMemberDecls here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not call getSingleModuleMemberDecls here?

I think that's what I originally had wanted and didn't finish while were debugging the tests. Thanks, I'll update it.


match decls with
| [ SynModuleDecl.DoExpr (_, expr, _) ] -> expr
| _ -> failwith "Can't get single expression"


let parseSourceCodeAndGetModule (source: string) =
parseSourceCode ("test.fsx", source) |> getSingleModuleLikeDecl

Expand Down
Loading