diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 6bcea07ddc1..dc28331da25 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1697,4 +1697,5 @@ featureEscapeBracesInFormattableString,"Escapes curly braces before calling Form 3565,parsExpectingType,"Expecting type" featureInformationalObjInferenceDiagnostic,"Diagnostic 3559 (warn when obj inferred) at informational level, off by default" 3566,tcMultipleRecdTypeChoice,"Multiple type matches were found:\n%s\nThe type '%s' was used. Due to the overlapping field names\n%s\nconsider using type annotations or change the order of open statements." -3567,parsMissingMemberBody,"Expecting member body" \ No newline at end of file +3567,parsMissingMemberBody,"Expecting member body" +3568,parsMissingKeyword,"Missing keyword '%s'" \ No newline at end of file diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index 5821534137a..80929510001 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -1090,3 +1090,12 @@ let appendValToLeadingKeyword mVal leadingKeyword = | SynLeadingKeyword.Override mOverride -> SynLeadingKeyword.OverrideVal(mOverride, mVal) | SynLeadingKeyword.Default (mDefault) -> SynLeadingKeyword.DefaultVal(mDefault, mVal) | _ -> leadingKeyword + +let mkSynUnionCase attributes (access: SynAccess option) id kind mDecl (xmlDoc, mBar) = + match access with + | Some access -> errorR (Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations (), access.Range)) + | _ -> () + + let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } + let mDecl = unionRangeWithXmlDoc xmlDoc mDecl + SynUnionCase(attributes, id, kind, xmlDoc, None, mDecl, trivia) diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi index 8d158862f4f..326a806e131 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fsi +++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi @@ -238,3 +238,12 @@ val checkForMultipleAugmentations: m: range -> a1: 'a list -> a2: 'a list -> 'a val rangeOfLongIdent: lid: LongIdent -> range val appendValToLeadingKeyword: mVal: range -> leadingKeyword: SynLeadingKeyword -> SynLeadingKeyword + +val mkSynUnionCase: + attributes: SynAttributes -> + access: SynAccess option -> + id: SynIdent -> + kind: SynUnionCaseKind -> + mDecl: range -> + (PreXmlDoc * range) -> + SynUnionCase diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index da62e142c25..104e89ee693 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -2485,69 +2485,36 @@ attrUnionCaseDecls: /* The core of a union case definition */ attrUnionCaseDecl: | opt_attributes opt_access unionCaseName - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - let mDecl = rhs parseState 3 - (fun (xmlDoc, mBar) -> - let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } - let mDecl = unionRangeWithXmlDoc xmlDoc mDecl - Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } + { mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields []) (rhs2 parseState 1 3) >> Choice2Of2 } | opt_attributes opt_access recover - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - (fun (xmlDoc, mBar) -> - let id = SynIdent(mkSynId mBar.EndRange "", None) - let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } - let mDecl = unionRangeWithXmlDoc xmlDoc mBar - Choice2Of2 (SynUnionCase ($1, id, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } + { fun (xmlDoc, mBar) -> mkSynUnionCase $1 $2 (SynIdent(mkSynId mBar.EndRange "", None)) (SynUnionCaseKind.Fields []) mBar (xmlDoc, mBar) |> Choice2Of2 } | opt_attributes opt_access unionCaseName OF unionCaseRepr - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - let mDecl = rhs2 parseState 1 5 - (fun (xmlDoc, mBar) -> - let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } - let mDecl = unionRangeWithXmlDoc xmlDoc mDecl - Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.Fields $5, xmlDoc, None, mDecl, trivia))) } + { mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields $5) (rhs2 parseState 1 5) >> Choice2Of2 } + + | opt_attributes opt_access unionCaseName unionCaseRepr + { errorR (Error(FSComp.SR.parsMissingKeyword("of"), rhs2 parseState 3 4)) + mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields $4) (rhs2 parseState 1 4) >> Choice2Of2 } | opt_attributes opt_access OF unionCaseRepr - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - let mOf = rhs parseState 3 + { let mOf = rhs parseState 3 let mId = mOf.StartRange errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf)) - let mDecl = rhs2 parseState 1 4 - (fun (xmlDoc, mBar) -> - let id = SynIdent(mkSynId mId "", None) - let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } - let mDecl = unionRangeWithXmlDoc xmlDoc mDecl - Choice2Of2(SynUnionCase($1, id, SynUnionCaseKind.Fields $4, xmlDoc, None, mDecl, trivia))) } + mkSynUnionCase $1 $2 (SynIdent(mkSynId mId "", None)) (SynUnionCaseKind.Fields $4) (rhs2 parseState 1 4) >> Choice2Of2 } | opt_attributes opt_access OF recover - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - let mOf = rhs parseState 3 + { let mOf = rhs parseState 3 let mId = mOf.StartRange errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf)) - let mDecl = rhs2 parseState 1 3 - (fun (xmlDoc, mBar) -> - let id = SynIdent(mkSynId mId "", None) - let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } - let mDecl = unionRangeWithXmlDoc xmlDoc mDecl - Choice2Of2(SynUnionCase($1, id, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } + mkSynUnionCase $1 $2 (SynIdent(mkSynId mId "", None)) (SynUnionCaseKind.Fields []) (rhs2 parseState 1 3) >> Choice2Of2 } | opt_attributes opt_access unionCaseName OF recover - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - let mDecl = rhs2 parseState 1 4 - (fun (xmlDoc, mBar) -> - let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } - let mDecl = unionRangeWithXmlDoc xmlDoc mDecl - Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } + { mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields []) (rhs2 parseState 1 4) >> Choice2Of2 } | opt_attributes opt_access unionCaseName COLON topType - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) - if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState) - let mDecl = rhs2 parseState 1 5 - (fun (xmlDoc, mBar) -> - let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } - let mDecl = unionRangeWithXmlDoc xmlDoc mDecl - Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.FullType $5, xmlDoc, None, mDecl, trivia))) } + { if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState) + mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.FullType $5) (rhs2 parseState 1 5) >> Choice2Of2 } | opt_attributes opt_access unionCaseName EQUALS atomicExpr { if Option.isSome $2 then errorR(Error(FSComp.SR.parsEnumFieldsCannotHaveVisibilityDeclarations(), rhs parseState 2)) diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 0f193395113..a265ab0ca83 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -822,6 +822,11 @@ Neúplný výraz operátoru (například^b) nebo volání kvalifikovaného typu (příklad: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index ea4855ac074..316b3ebc528 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -822,6 +822,11 @@ Unvollständiger Operatorausdruck (Beispiel: a^b) oder qualifizierter Typaufruf (Beispiel: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 5c35f12bd36..8f943c16b9c 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -822,6 +822,11 @@ Expresión de operador incompleta (ejemplo, a^b) o invocación de tipo calificada (ejemplo: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 68ea4e0a5f9..3f2f37284ea 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -822,6 +822,11 @@ Expression d’opérateur incomplète (exemple a^b) ou appel de type qualifié (exemple : ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 41125e76442..dfa6b93cebe 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -822,6 +822,11 @@ Espressione operatore incompleta (ad esempio a^b) o chiamata di tipo qualificato (ad esempio: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 3a04711e3d8..f2dbd41c37d 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -822,6 +822,11 @@ 不完全な演算子式 (例 a^b) または修飾型の呼び出し (例: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 9b1aef419fd..343da8aa6c6 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -822,6 +822,11 @@ 불완전한 연산자 식(예: a^b) 또는 정규화된 형식 호출(예: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index ec1a302e956..f9718508364 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -822,6 +822,11 @@ Niekompletne wyrażenie operatora (na przykład a^b) lub wywołanie typu kwalifikowanego (przykład: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index c875dabd6a2..ef0bb265690 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -822,6 +822,11 @@ Expressão de operador incompleta (exemplo a^b) ou invocação de tipo qualificado (exemplo: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index b7ae9790eb0..bd87c11346d 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -822,6 +822,11 @@ Неполное выражение оператора (например, a^b) или вызов квалифицированного типа (например, ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index d3609d35fdb..de53d2b32be 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -822,6 +822,11 @@ Eksik işleç ifadesi (örnek a^b) veya tam tür çağrısı (örnek: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 9d700a9f7c9..7ffc6c7c4a2 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -822,6 +822,11 @@ 运算符表达式不完整(示例: a^b)或限定类型调用(示例: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 08dce83131f..036b4f42631 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -822,6 +822,11 @@ 不完整的運算子運算式 (範例 a^b) 或限定類型調用 (範例: ^T.Name) + + Missing keyword '{0}' + Missing keyword '{0}' + + Expecting member body Expecting member body diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs b/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs new file mode 100644 index 00000000000..e44e99bbcbb --- /dev/null +++ b/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs @@ -0,0 +1,11 @@ +module Module + +let a = () + +type U = + | Case1 + | Case2 string + | Case3 of int + | Case4 4 + +let b = () diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs.bsl new file mode 100644 index 00000000000..61ef3fc7998 --- /dev/null +++ b/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs.bsl @@ -0,0 +1,86 @@ +ImplFile + (ParsedImplFileInput + ("/root/UnionCase/Missing keyword of.fs", false, QualifiedNameOfFile Module, + [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Named (SynIdent (a, None), false, None, (3,4--3,5)), None, + Const (Unit, (3,8--3,10)), (3,4--3,5), Yes (3,0--3,10), + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--3,10)); + Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [U], + PreXmlDoc ((5,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (5,5--5,6)), + Simple + (Union + (None, + [SynUnionCase + ([], SynIdent (Case1, None), Fields [], + PreXmlDoc ((6,4), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,6--6,11), { BarRange = Some (6,4--6,5) }); + SynUnionCase + ([], SynIdent (Case2, None), + Fields + [SynField + ([], false, None, + LongIdent + (SynLongIdent ([string], [], [None])), false, + PreXmlDoc ((7,12), FSharp.Compiler.Xml.XmlDocCollector), + None, (7,12--7,18), { LeadingKeyword = None })], + PreXmlDoc ((7,4), FSharp.Compiler.Xml.XmlDocCollector), + None, (7,6--7,18), { BarRange = Some (7,4--7,5) }); + SynUnionCase + ([], SynIdent (Case3, None), + Fields + [SynField + ([], false, None, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((8,15), FSharp.Compiler.Xml.XmlDocCollector), + None, (8,15--8,18), { LeadingKeyword = None })], + PreXmlDoc ((8,4), FSharp.Compiler.Xml.XmlDocCollector), + None, (8,6--8,18), { BarRange = Some (8,4--8,5) }); + SynUnionCase + ([], SynIdent (Case4, None), + Fields + [SynField + ([], false, None, + StaticConstant (Int32 4, (9,12--9,13)), false, + PreXmlDoc ((9,12), FSharp.Compiler.Xml.XmlDocCollector), + None, (9,12--9,13), { LeadingKeyword = None })], + PreXmlDoc ((9,4), FSharp.Compiler.Xml.XmlDocCollector), + None, (9,6--9,13), { BarRange = Some (9,4--9,5) })], + (6,4--9,13)), (6,4--9,13)), [], None, (5,5--9,13), + { LeadingKeyword = Type (5,0--5,4) + EqualsRange = Some (5,7--5,8) + WithKeyword = None })], (5,0--9,13)); + Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((11,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Named (SynIdent (b, None), false, None, (11,4--11,5)), None, + Const (Unit, (11,8--11,10)), (11,4--11,5), Yes (11,0--11,10), + { LeadingKeyword = Let (11,0--11,3) + InlineKeyword = None + EqualsRange = Some (11,6--11,7) })], (11,0--11,10))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--11,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(7,6)-(7,18) parse error Missing keyword 'of' +(9,6)-(9,13) parse error Missing keyword 'of' diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl index a9b9069f2bf..a258d294e96 100644 --- a/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl +++ b/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl @@ -41,5 +41,5 @@ ImplFile { ConditionalDirectives = [] CodeComments = [] }, set [])) -(5,6)-(5,14) parse error Accessibility modifiers are not permitted on union cases. Use 'type U = internal ...' or 'type U = private ...' to give an accessibility to the whole representation. (5,15)-(5,17) parse error Missing union case name +(5,6)-(5,14) parse error Accessibility modifiers are not permitted on union cases. Use 'type U = internal ...' or 'type U = private ...' to give an accessibility to the whole representation. diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing name 06.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Missing name 06.fs.bsl index 41a4bf12268..27516955a99 100644 --- a/tests/service/data/SyntaxTree/UnionCase/Missing name 06.fs.bsl +++ b/tests/service/data/SyntaxTree/UnionCase/Missing name 06.fs.bsl @@ -35,5 +35,5 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected symbol '|' in union case -(5,6)-(5,14) parse error Accessibility modifiers are not permitted on union cases. Use 'type U = internal ...' or 'type U = private ...' to give an accessibility to the whole representation. (5,15)-(5,17) parse error Missing union case name +(5,6)-(5,14) parse error Accessibility modifiers are not permitted on union cases. Use 'type U = internal ...' or 'type U = private ...' to give an accessibility to the whole representation.