Skip to content
Open
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
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
* Fix signature generation: type params with special characters missing backtick escaping. ([Issue #19595](https://github.com/dotnet/fsharp/issues/19595), [PR #19609](https://github.com/dotnet/fsharp/pull/19609))
* Fix internal error when using custom attribute with `[<Optional>]` value type parameter and no `[<DefaultParameterValue>]`. ([Issue #8353](https://github.com/dotnet/fsharp/issues/8353), [PR #19484](https://github.com/dotnet/fsharp/pull/19484))
* Fix parallel compilation of scripts ([PR #19649](https://github.com/dotnet/fsharp/pull/19649))
* Fix parser recovery, name resolution, and code completion for unfinished enum patterns ([PR #19708](https://github.com/dotnet/fsharp/pull/19708))

### Added

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/NameResolution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3531,7 +3531,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa
match extraDotAtTheEnd with
| ExtraDotAfterIdentifier.Yes ->
match LookupTypeNameInEnvNoArity fullyQualified id.idText nenv with
| tcref :: _ when tcref.IsUnionTycon ->
| tcref :: _ when tcref.IsUnionTycon || tcref.IsEnumTycon ->
let res = ResolutionInfo.Empty.AddEntity (id.idRange, tcref)
ResolutionInfo.SendEntityPathToSink (sink, ncenv, nenv, ItemOccurrence.Pattern, ad, res, ResultTyparChecker(fun () -> true))
Item.Types (id.idText, [ mkWoNullAppTy tcref [] ])
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,7 @@ type internal TypeCheckInfo
/// Is the item suitable for completion in a pattern
let IsPatternCandidate (item: CompletionItem) =
match item.Item with
| Item.RecdField f -> f.Tycon.IsEnumTycon
| Item.Value v -> v.LiteralValue.IsSome
| Item.ILField field -> field.LiteralValue.IsSome
| Item.ActivePatternCase _
Expand Down
6 changes: 6 additions & 0 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ let parse_error_rich = Some(fun (ctxt: ParseErrorContext<_>) ->

/* start with lowest */

%nonassoc prec_atompat_pathop_error
%nonassoc prec_args_error /* less than RPAREN */
%nonassoc prec_atomexpr_lparen_error /* less than RPAREN */

Expand Down Expand Up @@ -6929,6 +6930,11 @@ pathOp:
{ let ident, trivia = $1
SynLongIdent([ident], [], [Some trivia]) }

| ident DOT %prec prec_atompat_pathop_error
{ let mDot = rhs parseState 2
reportParseErrorAt mDot.EndRange (FSComp.SR.parsIdentifierExpected())
SynLongIdent([$1], [mDot], [None]) }

| ident DOT pathOp
{ prependIdentInLongIdentWithTrivia (SynIdent($1, None)) (rhs parseState 2) $3 }

Expand Down
39 changes: 39 additions & 0 deletions tests/FSharp.Compiler.Service.Tests/CompletionTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,45 @@ module Module =
"""
assertHasNoItemsWithNames ["E"] info

[<Fact>]
let ``Pattern - Enum 01`` () =
let info =
Checker.getCompletionInfo """
namespace Ns1
type E =
| A = 1
| B = 2

namespace Ns2

open Ns1

module M =
match E.A with
| E.{caret}
"""
assertHasItemWithNames ["A"] info

[<Fact>]
let ``Pattern - Enum 02`` () =
let info =
Checker.getCompletionInfo """
namespace Ns1
type E =
| A = 1
| B = 2

namespace Ns2

open Ns1

module M =
match E.A with
| E.{caret}
| E.B -> ()
"""
assertHasItemWithNames ["A"] info

#if NETCOREAPP
[<Fact>]
let ``Span appears in completion and is not marked obsolete`` () =
Expand Down
6 changes: 5 additions & 1 deletion tests/FSharp.Compiler.Service.Tests/SyntaxTreeTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ let private sanitizeAST (sourceDirectoryValue: string) (ast: ParsedInput) : Pars

let parseSourceCode (name: string, code: string) =
let location = Path.Combine(RootDirectory, name).Replace("\\", "/")
Range.setTestSource location code

let parseResults =
checker.ParseFile(
Expand Down Expand Up @@ -188,7 +189,10 @@ let ParseFile fileName =
let equals = expected = actual
let testUpdateBSLEnv = System.Environment.GetEnvironmentVariable("TEST_UPDATE_BSL")

if not (isNull testUpdateBSLEnv) && testUpdateBSLEnv.Trim() = "1" && not equals then
let shouldUpdateBaseline =
(not (isNull testUpdateBSLEnv) && testUpdateBSLEnv.Trim() = "1" && not equals)

if shouldUpdateBaseline then
File.WriteAllText(bslPath, actual)
elif not equals then
File.WriteAllText(actualPath, actual)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,76 @@ let o: obj = null
if true then
o.GetHashCode{caret}
"""

module Patterns =
[<Fact>]
let ``Enum - Type 01`` () =
assertHasSymbolUsageAtCaret "E" """
type E =
| A = 1

match E.A with
| E{caret}.A -> ()
"""

[<Fact>]
let ``Enum - Type 02`` () =
assertHasSymbolUsageAtCaret "E" """
type E =
| A = 1

match E.A with
| E{caret} -> ()
"""

[<Fact>]
let ``Enum - Type 03`` () =
assertHasSymbolUsageAtCaret "E" """
type E =
| A = 1

match E.A with
| E{caret}
"""

[<Fact>]
let ``Enum - Type 04`` () =
assertHasSymbolUsageAtCaret "E" """
type E =
| A = 1

match E.A with
| E{caret}.
"""

[<Fact>]
let ``Enum - Type 05`` () =
assertHasSymbolUsageAtCaret "E" """
type E =
| A = 1

match E.A with
| E{caret}. -> ()
"""

[<Fact(Skip = "Improve name resolution recovery")>]
let ``Enum - Type 06`` () =
assertHasSymbolUsageAtCaret "E" """
type E =
| A = 1

match E.A with
| E{caret}.B
"""

[<Fact>]
let ``Enum - Type 07`` () =
assertHasSymbolUsageAtCaret "E" """
type E =
| A = 1

match E.A with
| E{caret}.

()
"""
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ ImplFile
WarnDirectives = []
CodeComments = [] }, set []))

(4,18)-(5,5) parse error Incomplete structured construct at or before this point in object expression
(4,17)-(4,17) parse error Identifier expected
(4,18)-(5,5) parse error Expecting member body
2 changes: 1 addition & 1 deletion tests/service/data/SyntaxTree/Member/Member 03.fs.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,5 @@ ImplFile
WarnDirectives = []
CodeComments = [] }, set []))

(5,23)-(6,4) parse error Incomplete structured construct at or before this point in member definition
(5,22)-(5,22) parse error Identifier expected
(5,23)-(6,4) parse error Expecting member body
2 changes: 1 addition & 1 deletion tests/service/data/SyntaxTree/Member/Member 07.fs.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,4 @@ ImplFile
WarnDirectives = []
CodeComments = [] }, set []))

(5,23)-(5,24) parse error Unexpected symbol '=' in member definition
(5,22)-(5,22) parse error Identifier expected
4 changes: 4 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 01.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

match e with
| E -> ()
21 changes: 21 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 01.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
ImplFile
(ParsedImplFileInput
("/root/Pattern/Identifier 01.fs", false, QualifiedNameOfFile Module, [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(Match
(Yes (3,0--3,12), Ident e,
[SynMatchClause
(LongIdent
(SynLongIdent ([E], [], [None]), None, None, Pats [],
None, (4,2--4,3)), None, Const (Unit, (4,7--4,9)),
(4,2--4,9), Yes, { ArrowRange = Some (4,4--4,6)
BarRange = Some (4,0--4,1) })],
(3,0--4,9), { MatchKeyword = (3,0--3,5)
WithKeyword = (3,8--3,12) }), (3,0--4,9))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
WarnDirectives = []
CodeComments = [] }, set []))
4 changes: 4 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 02.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

match e with
| e -> ()
20 changes: 20 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 02.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
ImplFile
(ParsedImplFileInput
("/root/Pattern/Identifier 02.fs", false, QualifiedNameOfFile Module, [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(Match
(Yes (3,0--3,12), Ident e,
[SynMatchClause
(Named (SynIdent (e, None), false, None, (4,2--4,3)), None,
Const (Unit, (4,7--4,9)), (4,2--4,9), Yes,
{ ArrowRange = Some (4,4--4,6)
BarRange = Some (4,0--4,1) })], (3,0--4,9),
{ MatchKeyword = (3,0--3,5)
WithKeyword = (3,8--3,12) }), (3,0--4,9))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
WarnDirectives = []
CodeComments = [] }, set []))
4 changes: 4 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 03.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

match e with
| E
24 changes: 24 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 03.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
ImplFile
(ParsedImplFileInput
("/root/Pattern/Identifier 03.fs", false, QualifiedNameOfFile Module, [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(Match
(Yes (3,0--3,12), Ident e,
[SynMatchClause
(LongIdent
(SynLongIdent ([E], [], [None]), None, None, Pats [],
None, (4,2--4,3)), None,
ArbitraryAfterError ("patternClauses2", (4,3--4,3)),
(4,2--4,3), Yes, { ArrowRange = None
BarRange = Some (4,0--4,1) })],
(3,0--4,3), { MatchKeyword = (3,0--3,5)
WithKeyword = (3,8--3,12) }), (3,0--4,3))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,3), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
WarnDirectives = []
CodeComments = [] }, set []))

(4,0)-(4,3) parse error Incomplete structured construct at or before this point in pattern matching. Expected '->' or other token.
4 changes: 4 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 04.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

match e with
| e
22 changes: 22 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 04.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
ImplFile
(ParsedImplFileInput
("/root/Pattern/Identifier 04.fs", false, QualifiedNameOfFile Module, [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(Match
(Yes (3,0--3,12), Ident e,
[SynMatchClause
(Named (SynIdent (e, None), false, None, (4,2--4,3)), None,
ArbitraryAfterError ("patternClauses2", (4,3--4,3)),
(4,2--4,3), Yes, { ArrowRange = None
BarRange = Some (4,0--4,1) })],
(3,0--4,3), { MatchKeyword = (3,0--3,5)
WithKeyword = (3,8--3,12) }), (3,0--4,3))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,3), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
WarnDirectives = []
CodeComments = [] }, set []))

(4,0)-(4,3) parse error Incomplete structured construct at or before this point in pattern matching. Expected '->' or other token.
4 changes: 4 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 05.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

match e with
| E.
25 changes: 25 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 05.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
ImplFile
(ParsedImplFileInput
("/root/Pattern/Identifier 05.fs", false, QualifiedNameOfFile Module, [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(Match
(Yes (3,0--3,12), Ident e,
[SynMatchClause
(LongIdent
(SynLongIdent ([E], [(4,3--4,4)], [None]), None, None,
Pats [], None, (4,2--4,4)), None,
ArbitraryAfterError ("patternClauses2", (4,4--4,4)),
(4,2--4,4), Yes, { ArrowRange = None
BarRange = Some (4,0--4,1) })],
(3,0--4,4), { MatchKeyword = (3,0--3,5)
WithKeyword = (3,8--3,12) }), (3,0--4,4))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,4), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
WarnDirectives = []
CodeComments = [] }, set []))

(4,4)-(4,4) parse error Identifier expected
(4,0)-(4,4) parse error Incomplete structured construct at or before this point in pattern matching. Expected '->' or other token.
6 changes: 6 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 06.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Module

match e with
| E.

()
26 changes: 26 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 06.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
ImplFile
(ParsedImplFileInput
("/root/Pattern/Identifier 06.fs", false, QualifiedNameOfFile Module, [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(Match
(Yes (3,0--3,12), Ident e,
[SynMatchClause
(LongIdent
(SynLongIdent ([E], [(4,3--4,4)], [None]), None, None,
Pats [], None, (4,2--4,4)), None,
ArbitraryAfterError ("patternClauses2", (4,4--4,4)),
(4,2--4,4), Yes, { ArrowRange = None
BarRange = Some (4,0--4,1) })],
(3,0--4,4), { MatchKeyword = (3,0--3,5)
WithKeyword = (3,8--3,12) }), (3,0--4,4));
Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
WarnDirectives = []
CodeComments = [] }, set []))

(4,4)-(4,4) parse error Identifier expected
(6,0)-(6,1) parse error Incomplete structured construct at or before this point in pattern matching. Expected '->' or other token.
7 changes: 7 additions & 0 deletions tests/service/data/SyntaxTree/Pattern/Identifier 07.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Module

do
match e with
| E.

()
Loading
Loading