diff --git a/src/fsharp/CompilerDiagnostics.fs b/src/fsharp/CompilerDiagnostics.fs index c689c68deb3..d0f80e1da0e 100644 --- a/src/fsharp/CompilerDiagnostics.fs +++ b/src/fsharp/CompilerDiagnostics.fs @@ -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 diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index 7d12a8e6965..76bfd822d31 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -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 + [] type SynPat = diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index 8e676ea3b4e..97a766b8ff5 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -1148,6 +1148,8 @@ type SynArgPats = pats: (Ident * SynPat) list * range: range + member Patterns: SynPat list + /// Represents a syntax tree for an F# pattern [] type SynPat = diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index cbbdece5bd2..768428b0c33 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -316,6 +316,8 @@ let rangeOfLongIdent(lid:LongIdent) = %type ident %type typ typEOF %type tyconSpfnList +%type atomicPatsOrNamePatPairs +%type atomicPatterns %type patternResult %type declExpr %type minusExpr @@ -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: @@ -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) } @@ -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) + SynArgPats.Pats $1, m } atomicPatterns: | atomicPattern atomicPatterns %prec pat_args @@ -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 @@ -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 diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index eff845781d5..23462238334 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -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 @@ -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 @@ -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 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 15cf4603032..07fb8a7e5c4 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -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 @@ -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 @@ -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 diff --git a/tests/fsharp/typecheck/sigs/neg104.bsl b/tests/fsharp/typecheck/sigs/neg104.bsl index 022a8e3e4b2..e93db87ef8d 100644 --- a/tests/fsharp/typecheck/sigs/neg104.bsl +++ b/tests/fsharp/typecheck/sigs/neg104.bsl @@ -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 diff --git a/tests/fsharp/typecheck/sigs/neg104.vsbsl b/tests/fsharp/typecheck/sigs/neg104.vsbsl index e4e6e79397a..87d4a4e89db 100644 --- a/tests/fsharp/typecheck/sigs/neg104.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg104.vsbsl @@ -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 @@ -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'. diff --git a/tests/fsharp/typecheck/sigs/neg80.vsbsl b/tests/fsharp/typecheck/sigs/neg80.vsbsl index 26c5bcafa24..63aba7d33db 100644 --- a/tests/fsharp/typecheck/sigs/neg80.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg80.vsbsl @@ -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). diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_KeywordIdent01.fs b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_KeywordIdent01.fs index 7c185078802..5aeec2e163f 100644 --- a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_KeywordIdent01.fs +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_KeywordIdent01.fs @@ -2,7 +2,7 @@ #light //Unexpected keyword 'type' in binding -//Unexpected keyword 'class' in pattern +//Unexpected keyword 'class' in binding. Expected '=' or other token. let type = 2 diff --git a/tests/fsharpqa/Source/Conformance/PatternMatching/TypeConstraint/E_typecontraint01.fs b/tests/fsharpqa/Source/Conformance/PatternMatching/TypeConstraint/E_typecontraint01.fs index b43a8a2927d..4ce19c52666 100644 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/TypeConstraint/E_typecontraint01.fs +++ b/tests/fsharpqa/Source/Conformance/PatternMatching/TypeConstraint/E_typecontraint01.fs @@ -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. -//Unexpected symbol ':>' in pattern$ -//Unmatched '\('$ +//Unexpected symbol ':>' in pattern. Expected '\)' or other token. +//Unmatched '\('$ +//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. type A() = class end diff --git a/tests/fsharpqa/Source/Diagnostics/General/E_UnexpectedSymbol01.fs b/tests/fsharpqa/Source/Diagnostics/General/E_UnexpectedSymbol01.fs index 67024e490cc..cd83283d263 100644 --- a/tests/fsharpqa/Source/Diagnostics/General/E_UnexpectedSymbol01.fs +++ b/tests/fsharpqa/Source/Diagnostics/General/E_UnexpectedSymbol01.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:2099 // Regression test for FSHARP1.0:2670 -//Unexpected symbol '<-' in pattern +//Unexpected symbol '<-' in binding. Expected '=' or other token. //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. //lambda diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/E_let_id.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/E_let_id.fsx index 9fac116ed39..09150ddb8e8 100644 --- a/tests/fsharpqa/Source/InteractiveSession/Misc/E_let_id.fsx +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/E_let_id.fsx @@ -1,5 +1,5 @@ // #Regression #NoMT #FSI // Regression test for FSHARP1.0:5629 -//Incomplete structured construct at or before this point in pattern$ +//Incomplete structured construct at or before this point in binding. Expected '=' or other token. let f;; exit 1;; diff --git a/tests/service/Common.fs b/tests/service/Common.fs index d0105acca52..27031dbcd16 100644 --- a/tests/service/Common.fs +++ b/tests/service/Common.fs @@ -253,6 +253,16 @@ let getSingleModuleLikeDecl (input: ParsedInput) = | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ decl ])) -> decl | _ -> failwith "Could not get module decls" +let getSingleModuleMemberDecls (input: ParsedInput) = + let (SynModuleOrNamespace (decls = decls)) = getSingleModuleLikeDecl input + decls + +let getSingleExprInModule (input: ParsedInput) = + match getSingleModuleMemberDecls input with + | [ SynModuleDecl.DoExpr (_, expr, _) ] -> expr + | _ -> failwith "Can't get single expression" + + let parseSourceCodeAndGetModule (source: string) = parseSourceCode ("test.fsx", source) |> getSingleModuleLikeDecl diff --git a/tests/service/ParserTests.fs b/tests/service/ParserTests.fs index 76acd1ba6aa..8e35c0fc4ca 100644 --- a/tests/service/ParserTests.fs +++ b/tests/service/ParserTests.fs @@ -1,28 +1,27 @@ -module Tests.Parser +module FSharp.Compiler.Service.Tests.Parser.Recovery open FSharp.Compiler.Service.Tests.Common open FSharp.Compiler.Syntax open NUnit.Framework -module Recovery = - [] - let ``Unfinished interface member`` () = - let parseResults = getParseResults """ +[] +let ``Interface impl - No members`` () = + let parseResults = getParseResults """ type T = interface I with member x.P2 = () let x = () """ - let (SynModuleOrNamespace (decls = decls)) = getSingleModuleLikeDecl parseResults - match decls with - | [ SynModuleDecl.Types ([ SynTypeDefn (typeRepr = SynTypeDefnRepr.ObjectModel (members = [ _; _ ])) ], _) - SynModuleDecl.Let _ ] -> () - | _ -> failwith "Unexpected tree" - - [] - let ``Union case 01 - of`` () = - let parseResults = getParseResults """ + match getSingleModuleMemberDecls parseResults with + | [ SynModuleDecl.Types ([ SynTypeDefn (typeRepr = SynTypeDefnRepr.ObjectModel (members = [ _; _ ])) ], _) + SynModuleDecl.Let _ ] -> () + | _ -> failwith "Unexpected tree" + + +[] +let ``Union case 01 - of`` () = + let parseResults = getParseResults """ type U1 = | A of @@ -31,16 +30,75 @@ type U2 = | C let x = () - """ - let (|UnionWithCases|_|) typeDefn = - match typeDefn with - | SynTypeDefn (typeRepr = SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (unionCases = cases), _)) -> - cases |> List.map (fun (SynUnionCase (ident = ident)) -> ident.idText) |> Some - | _ -> None - - let (SynModuleOrNamespace (decls = decls)) = getSingleModuleLikeDecl parseResults - match decls with - | [ SynModuleDecl.Types ([ UnionWithCases ["A"]], _) - SynModuleDecl.Types ([ UnionWithCases ["B"; "C"] ], _) - SynModuleDecl.Let _ ] -> () - | _ -> failwith "Unexpected tree" +""" + let (|UnionWithCases|_|) typeDefn = + match typeDefn with + | SynTypeDefn (typeRepr = SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (unionCases = cases), _)) -> + cases |> List.map (fun (SynUnionCase (ident = ident)) -> ident.idText) |> Some + | _ -> None + + match getSingleModuleMemberDecls parseResults with + | [ SynModuleDecl.Types ([ UnionWithCases ["A"]], _) + SynModuleDecl.Types ([ UnionWithCases ["B"; "C"] ], _) + SynModuleDecl.Let _ ] -> () + | _ -> failwith "Unexpected tree" + + +[] +let ``Match clause 01`` () = + let parseResults = getParseResults """ +match () with +| x +""" + match getSingleExprInModule parseResults with + | SynExpr.Match (_, _, [ SynMatchClause (_, _, _, SynExpr.ArbitraryAfterError _, _, _) ], _) -> () + | _ -> failwith "Unexpected tree" + + +[] +let ``Match clause 02 - When`` () = + let parseResults = getParseResults """ +match () with +| x when true +""" + + match getSingleExprInModule parseResults with + | SynExpr.Match (_, _, [ SynMatchClause (_, _, _, SynExpr.ArbitraryAfterError _, _, _) ], _) -> () + | _ -> failwith "Unexpected tree" + +[] +let ``Match clause 03 - When`` () = + let parseResults = getParseResults """ +match () with +| x when true +| _ -> () +""" + + match getSingleExprInModule parseResults with + | SynExpr.Match (_, _, [ SynMatchClause (_, _, _, SynExpr.ArbitraryAfterError _, _, _); _ ], _) -> () + | _ -> failwith "Unexpected tree" + +[] +let ``Match clause 04 - Or pat`` () = + let parseResults = getParseResults """ +match () with +| x +| _ -> () +""" + + match getSingleExprInModule parseResults with + | SynExpr.Match (_, _, [ SynMatchClause (SynPat.Or _, _, _, SynExpr.Const _, _, _) ], _) -> () + | _ -> failwith "Unexpected tree" + +[] +let ``Match clause 05 - Missing body`` () = + let parseResults = getParseResults """ +match () with +| x -> +| _ -> () +""" + + match getSingleExprInModule parseResults with + | SynExpr.Match (_, _, [ SynMatchClause (_, _, _, SynExpr.ArbitraryAfterError _, _, _) + SynMatchClause (_, _, _, SynExpr.Const _, _, _) ], _) -> () + | _ -> failwith "Unexpected tree" \ No newline at end of file diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs index 82bdd085587..675ee60617c 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs @@ -6239,7 +6239,7 @@ let rec f l = marker = "(*MarkerMethodInType*)", list = ["PrivateMethod"]) - [] +// [] member this.``VariableIdentifier.AsParameter``() = this.VerifyDotCompListContainAllAtStartOfMarker( fileContents = """