From 366f3fc075c3460cf10eee1c23eab30be485ca41 Mon Sep 17 00:00:00 2001
From: Thomas Boby
Date: Tue, 7 Jul 2020 20:56:11 +0100
Subject: [PATCH 1/5] Improve error reporting: Missing = on type declaration
---
src/fsharp/FSComp.txt | 1 +
src/fsharp/pars.fsy | 9 ++++++--
.../ErrorMessages/TypeEqualsMissingTests.fs | 21 +++++++++++++++++++
.../FSharp.Compiler.ComponentTests.fsproj | 1 +
4 files changed, 30 insertions(+), 2 deletions(-)
create mode 100644 tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt
index a8acd94267c..e00d846766a 100644
--- a/src/fsharp/FSComp.txt
+++ b/src/fsharp/FSComp.txt
@@ -1498,6 +1498,7 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
3351,chkFeatureNotRuntimeSupported,"Feature '%s' is not supported by target runtime."
3352,typrelInterfaceMemberNoMostSpecificImplementation,"Interface member '%s' does not have a most specific implementation."
3353,chkFeatureNotSupportedInLibrary,"Feature '%s' requires the F# library for language version %s or greater."
+3360,parsEqualsMissingInTypeDefinition,"Unexpected symbol in type definition. Did you forget to use the = operator?"
useSdkRefs,"Use reference assemblies for .NET framework references when available (Enabled by default)."
optsLangVersion,"Display the allowed values for language version, specify language version such as 'latest' or 'preview'"
optsSupportedLangVersions,"Supported language versions:"
diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy
index c9b4a5861bf..2764d44f99f 100644
--- a/src/fsharp/pars.fsy
+++ b/src/fsharp/pars.fsy
@@ -1496,8 +1496,9 @@ tyconDefn:
| typeNameInfo
{ TypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], $1.Range) }
- | typeNameInfo EQUALS tyconDefnRhsBlock
- { let nameRange = rhs parseState 1
+ | typeNameInfo type_opt_equals tyconDefnRhsBlock
+ { if not $2 then raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition())
+ let nameRange = rhs parseState 1
let (tcDefRepr:SynTypeDefnRepr), members = $3 nameRange
let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range
let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range)
@@ -5445,6 +5446,10 @@ deprecated_opt_equals:
| EQUALS { deprecatedWithError (FSComp.SR.parsNoEqualShouldFollowNamespace()) (lhs parseState); () }
| /* EMPTY */ { }
+type_opt_equals:
+ | EQUALS { true }
+ | /* EMPTY */ { false }
+
opt_OBLOCKSEP:
| OBLOCKSEP { }
| /* EMPTY */ { }
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
new file mode 100644
index 00000000000..aea137edf63
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace FSharp.Compiler.ErrorMessages.ComponentTests
+
+open Xunit
+open FSharp.Test.Utilities
+open FSharp.Compiler.SourceCodeServices
+
+
+module ``Type definition missing equals`` =
+
+ []
+ let ``Missing equals in DU``() =
+ CompilerAssert.TypeCheckSingleError
+ """
+type X | A | B
+ """
+ FSharpErrorSeverity.Error
+ 3360
+ (2, 8, 2, 9)
+ "Unexpected symbol in type definition. Did you forget to use the = operator?"
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 74d960c1c92..440a4e8cf94 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -22,6 +22,7 @@
+
From c044bcf9eb727764817167609180da280fb48d89 Mon Sep 17 00:00:00 2001
From: Thomas Boby
Date: Sun, 11 Oct 2020 15:25:05 +0100
Subject: [PATCH 2/5] Rename parser rule
---
src/fsharp/pars.fsy | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy
index 2764d44f99f..e1d1c80e94a 100644
--- a/src/fsharp/pars.fsy
+++ b/src/fsharp/pars.fsy
@@ -1496,7 +1496,7 @@ tyconDefn:
| typeNameInfo
{ TypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], $1.Range) }
- | typeNameInfo type_opt_equals tyconDefnRhsBlock
+ | typeNameInfo opt_equals tyconDefnRhsBlock
{ if not $2 then raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition())
let nameRange = rhs parseState 1
let (tcDefRepr:SynTypeDefnRepr), members = $3 nameRange
@@ -5446,7 +5446,7 @@ deprecated_opt_equals:
| EQUALS { deprecatedWithError (FSComp.SR.parsNoEqualShouldFollowNamespace()) (lhs parseState); () }
| /* EMPTY */ { }
-type_opt_equals:
+opt_equals:
| EQUALS { true }
| /* EMPTY */ { false }
From 2d4d77feb0ec34d2b0f2b3a01b886b4c9d366f06 Mon Sep 17 00:00:00 2001
From: Thomas Boby
Date: Sun, 11 Oct 2020 15:25:24 +0100
Subject: [PATCH 3/5] Update message to suggested wording
---
src/fsharp/FSComp.txt | 2 +-
.../ErrorMessages/TypeEqualsMissingTests.fs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt
index e00d846766a..d59eed8deca 100644
--- a/src/fsharp/FSComp.txt
+++ b/src/fsharp/FSComp.txt
@@ -1498,7 +1498,7 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
3351,chkFeatureNotRuntimeSupported,"Feature '%s' is not supported by target runtime."
3352,typrelInterfaceMemberNoMostSpecificImplementation,"Interface member '%s' does not have a most specific implementation."
3353,chkFeatureNotSupportedInLibrary,"Feature '%s' requires the F# library for language version %s or greater."
-3360,parsEqualsMissingInTypeDefinition,"Unexpected symbol in type definition. Did you forget to use the = operator?"
+3360,parsEqualsMissingInTypeDefinition,"Unexpected token in type definition. Expected '='."
useSdkRefs,"Use reference assemblies for .NET framework references when available (Enabled by default)."
optsLangVersion,"Display the allowed values for language version, specify language version such as 'latest' or 'preview'"
optsSupportedLangVersions,"Supported language versions:"
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
index aea137edf63..89c6c107dea 100644
--- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
@@ -18,4 +18,4 @@ type X | A | B
FSharpErrorSeverity.Error
3360
(2, 8, 2, 9)
- "Unexpected symbol in type definition. Did you forget to use the = operator?"
+ "Unexpected token in type definition. Expected '='."
From 601cba66a1647f0a2c216817241312320b05e313 Mon Sep 17 00:00:00 2001
From: Thomas Boby
Date: Mon, 12 Oct 2020 10:55:38 +0100
Subject: [PATCH 4/5] Move to correct test namespace
---
.../ErrorMessages/TypeEqualsMissingTests.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
index 89c6c107dea..7ee7df956ae 100644
--- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
@@ -1,6 +1,6 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
-namespace FSharp.Compiler.ErrorMessages.ComponentTests
+namespace FSharp.Compiler.ComponentTests.ErrorMessages
open Xunit
open FSharp.Test.Utilities
From a125c05182f4f577af3ca6a2c90f31d4150cc789 Mon Sep 17 00:00:00 2001
From: Thomas Boby
Date: Mon, 12 Oct 2020 11:55:31 +0100
Subject: [PATCH 5/5] Include typename in error message This is taken from the
end of the list of idents. While the spec says this should be an ident not a
long-ident, the parser doesn't enforce this, so we assume it has at least one
item but don't check.
---
src/fsharp/FSComp.txt | 2 +-
src/fsharp/pars.fsy | 7 ++++++-
.../ErrorMessages/TypeEqualsMissingTests.fs | 2 +-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt
index d59eed8deca..85defc1dbf6 100644
--- a/src/fsharp/FSComp.txt
+++ b/src/fsharp/FSComp.txt
@@ -1498,7 +1498,7 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
3351,chkFeatureNotRuntimeSupported,"Feature '%s' is not supported by target runtime."
3352,typrelInterfaceMemberNoMostSpecificImplementation,"Interface member '%s' does not have a most specific implementation."
3353,chkFeatureNotSupportedInLibrary,"Feature '%s' requires the F# library for language version %s or greater."
-3360,parsEqualsMissingInTypeDefinition,"Unexpected token in type definition. Expected '='."
+3360,parsEqualsMissingInTypeDefinition,"Unexpected token in type definition. Expected '=' after the type '%s'."
useSdkRefs,"Use reference assemblies for .NET framework references when available (Enabled by default)."
optsLangVersion,"Display the allowed values for language version, specify language version such as 'latest' or 'preview'"
optsSupportedLangVersions,"Supported language versions:"
diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy
index e1d1c80e94a..c6344e5104d 100644
--- a/src/fsharp/pars.fsy
+++ b/src/fsharp/pars.fsy
@@ -1497,7 +1497,12 @@ tyconDefn:
{ TypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], $1.Range) }
| typeNameInfo opt_equals tyconDefnRhsBlock
- { if not $2 then raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition())
+ { if not $2 then (
+ let (ComponentInfo(_, _, _, lid, _, _, _, _)) = $1
+ // While the spec doesn't allow long idents here, the parser doesn't enforce this, so take one ident
+ let typeNameId = List.last lid
+ raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition(typeNameId.ToString()))
+ )
let nameRange = rhs parseState 1
let (tcDefRepr:SynTypeDefnRepr), members = $3 nameRange
let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
index 7ee7df956ae..70d7beebc92 100644
--- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
@@ -18,4 +18,4 @@ type X | A | B
FSharpErrorSeverity.Error
3360
(2, 8, 2, 9)
- "Unexpected token in type definition. Expected '='."
+ "Unexpected token in type definition. Expected '=' after the type 'X'."