From 6279e4dde6030f87f5a747e3c5cb0dd0c6de0d59 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 5 Apr 2023 14:17:33 +0200 Subject: [PATCH 1/7] Parser: recover on unfinished identifiers in expressions --- src/Compiler/FSComp.txt | 3 +- src/Compiler/lex.fsl | 8 +- src/Compiler/pars.fsy | 3 + .../Expression/Unfinished escaped ident 01.fs | 46 +++++++ .../Unfinished escaped ident 01.fs.bsl | 115 ++++++++++++++++++ 5 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 9d26318039c..5c3ce3a938e 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1683,4 +1683,5 @@ featureEscapeBracesInFormattableString,"Escapes curly braces before calling Form 3559,typrelNeverRefinedAwayFromTop,"A type has been implicitly inferred as 'obj', which may be unintended. Consider adding explicit type annotations. You can disable this warning by using '#nowarn \"3559\"' or '--nowarn:3559'." 3560,tcCopyAndUpdateRecordChangesAllFields,"This copy-and-update record expression changes all fields of record type '%s'. Consider using the record construction syntax instead." 3561,chkAutoOpenAttributeInTypeAbbrev,"FSharp.Core.AutoOpenAttribute should not be aliased." -3562,parsUnexpectedEndOfFileElif,"Unexpected end of input in 'else if' or 'elif' branch of conditional expression. Expected 'elif then ' or 'else if then '." \ No newline at end of file +3562,parsUnexpectedEndOfFileElif,"Unexpected end of input in 'else if' or 'elif' branch of conditional expression. Expected 'elif then ' or 'else if then '." +3563,lexInvalidIdentifier,"This is not a valid identifier" \ No newline at end of file diff --git a/src/Compiler/lex.fsl b/src/Compiler/lex.fsl index 45057efa104..8c977fbc13e 100644 --- a/src/Compiler/lex.fsl +++ b/src/Compiler/lex.fsl @@ -701,9 +701,13 @@ rule token args skip = parse if not skip then WHITESPACE (LexCont.Token(args.ifdefStack, args.stringNest)) else token args skip lexbuf } - | '`' '`' ([^'`' '\n' '\r' '\t'] | '`' [^'`''\n' '\r' '\t']) + '`' '`' + | '`' '`' ([^'`' '\n' '\r' '\t'] | '`' [^'`''\n' '\r' '\t'])+ '`' '`' { Keywords.IdentifierToken args lexbuf (lexemeTrimBoth lexbuf 2 2) } + | ('`' '`' (([^'`' '\n' '\r' '\t'] | ("`"[^'`' '\n' '\r' '\t']))+)'`'?) | "````" | "```" | "``" | "`" + { errorR(Error(FSComp.SR.lexInvalidIdentifier(), lexbuf.LexemeRange)) + RESERVED } + | ('#' anywhite* | "#line" anywhite+ ) digit+ anywhite* ('@'? "\"" [^'\n''\r''"']+ '"')? anywhite* newline { let pos = lexbuf.EndPos if skip then @@ -898,8 +902,6 @@ rule token args skip = parse | "~" { RESERVED } - | "`" { RESERVED } - | ignored_op_char* '*' '*' op_char* { checkExprOp lexbuf; INFIX_STAR_STAR_OP(lexeme lexbuf) } | ignored_op_char* ('*' | '/'|'%') op_char* { checkExprOp lexbuf; INFIX_STAR_DIV_MOD_OP(lexeme lexbuf) } diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 496d70bae62..0b9322188d0 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4343,6 +4343,9 @@ atomicExpr: let lhsm = rhs2 parseState 1 2 SynExpr.Typar(typar, lhsm), false } + | RESERVED + { arbExpr ("unfinished identifier", rhs parseState 1), false } + | atomicExpr DOT atomicExprQualification { let arg1, hpa1 = $1 $3 arg1 (lhs parseState) (rhs parseState 2), hpa1 } diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs new file mode 100644 index 00000000000..199330b5379 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs @@ -0,0 +1,46 @@ +module Module + +do + ` + +do + `` + +do + ``` + +do + ```` + +do + `` `` + +do + ` `` ` + +do + ` `` `` + +do + ```````` + +do + ``````` + +do + `````` + +do + ````` + +do + ``` `` + +do + ``` ``` + +do + ````.P + +do + 1 + ` diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl new file mode 100644 index 00000000000..7cd4aaa32c4 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl @@ -0,0 +1,115 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Unfinished escaped ident 01.fs", false, + QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (Do + (ArbitraryAfterError ("unfinished identifier", (4,4--4,5)), + (3,0--4,5)), (3,0--4,5)); + Expr + (Do + (ArbitraryAfterError ("unfinished identifier", (7,4--7,7)), + (6,0--7,7)), (6,0--7,7)); + Expr + (Do + (ArbitraryAfterError ("unfinished identifier", (10,4--10,8)), + (9,0--10,8)), (9,0--10,8)); + Expr + (Do + (ArbitraryAfterError ("unfinished identifier", (13,4--13,8)), + (12,0--13,8)), (12,0--13,8)); + Expr (Do (Ident , (15,0--16,9)), (15,0--16,9)); + Expr + (Do + (App + (NonAtomic, false, + ArbitraryAfterError ("unfinished identifier", (19,4--19,5)), + ArbitraryAfterError ("unfinished identifier", (19,6--19,11)), + (19,4--19,11)), (18,0--19,11)), (18,0--19,11)); + Expr + (Do + (App + (NonAtomic, false, + ArbitraryAfterError ("unfinished identifier", (22,4--22,5)), + Ident , (22,4--22,11)), (21,0--22,11)), (21,0--22,11)); + Expr + (Do + (App + (NonAtomic, false, + ArbitraryAfterError ("unfinished identifier", (25,4--25,8)), + ArbitraryAfterError ("unfinished identifier", (25,8--25,12)), + (25,4--25,12)), (24,0--25,12)), (24,0--25,12)); + Expr + (Do + (App + (NonAtomic, false, + ArbitraryAfterError ("unfinished identifier", (28,4--28,8)), + ArbitraryAfterError ("unfinished identifier", (28,8--28,12)), + (28,4--28,12)), (27,0--28,12)), (27,0--28,12)); + Expr + (Do + (App + (NonAtomic, false, + ArbitraryAfterError ("unfinished identifier", (31,4--31,8)), + ArbitraryAfterError ("unfinished identifier", (31,8--31,11)), + (31,4--31,11)), (30,0--31,11)), (30,0--31,11)); + Expr + (Do + (App + (NonAtomic, false, + ArbitraryAfterError ("unfinished identifier", (34,4--34,8)), + ArbitraryAfterError ("unfinished identifier", (34,8--34,9)), + (34,4--34,9)), (33,0--34,9)), (33,0--34,9)); + Expr (Do (Ident ` , (36,0--37,10)), (36,0--37,10)); + Expr + (Do + (App + (NonAtomic, false, Ident ` , + ArbitraryAfterError + ("unfinished identifier", (40,10--40,11)), (40,4--40,11)), + (39,0--40,11)), (39,0--40,11)); + Expr + (Do + (DotGet + (ArbitraryAfterError ("unfinished identifier", (43,4--43,8)), + (43,8--43,9), SynLongIdent ([P], [], [None]), (43,4--43,10)), + (42,0--43,10)), (42,0--43,10)); + Expr + (Do + (App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], [Some (OriginalNotation "+")]), + None, (46,6--46,7)), Const (Int32 1, (46,4--46,5)), + (46,4--46,7)), + ArbitraryAfterError ("unfinished identifier", (46,8--46,9)), + (46,4--46,9)), (45,0--46,9)), (45,0--46,9))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--46,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(4,4)-(4,5) parse error This is not a valid identifier +(7,4)-(7,7) parse error This is not a valid identifier +(10,4)-(10,8) parse error This is not a valid identifier +(13,4)-(13,8) parse error This is not a valid identifier +(19,4)-(19,5) parse error This is not a valid identifier +(19,6)-(19,11) parse error This is not a valid identifier +(22,4)-(22,5) parse error This is not a valid identifier +(25,4)-(25,8) parse error This is not a valid identifier +(25,8)-(25,12) parse error This is not a valid identifier +(28,4)-(28,8) parse error This is not a valid identifier +(28,8)-(28,12) parse error This is not a valid identifier +(31,4)-(31,8) parse error This is not a valid identifier +(31,8)-(31,11) parse error This is not a valid identifier +(34,4)-(34,8) parse error This is not a valid identifier +(34,8)-(34,9) parse error This is not a valid identifier +(40,10)-(40,11) parse error This is not a valid identifier +(43,4)-(43,8) parse error This is not a valid identifier +(46,8)-(46,9) parse error This is not a valid identifier From d6bef5fad38b0af69db957e4dc2fb09ae630c71d Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 5 Apr 2023 14:47:27 +0200 Subject: [PATCH 2/7] Recover unfinished escaped indents in more cases --- src/Compiler/lex.fsl | 12 ++- src/Compiler/pars.fsy | 5 +- .../Unfinished escaped ident 01.fs.bsl | 65 +++++--------- .../Expression/Unfinished escaped ident 02.fs | 6 ++ .../Unfinished escaped ident 02.fs.bsl | 88 +++++++++++++++++++ .../Expression/Unfinished escaped ident 03.fs | 9 ++ .../Unfinished escaped ident 03.fs.bsl | 42 +++++++++ 7 files changed, 181 insertions(+), 46 deletions(-) create mode 100644 tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs.bsl diff --git a/src/Compiler/lex.fsl b/src/Compiler/lex.fsl index 8c977fbc13e..c9900ea1acd 100644 --- a/src/Compiler/lex.fsl +++ b/src/Compiler/lex.fsl @@ -704,9 +704,17 @@ rule token args skip = parse | '`' '`' ([^'`' '\n' '\r' '\t'] | '`' [^'`''\n' '\r' '\t'])+ '`' '`' { Keywords.IdentifierToken args lexbuf (lexemeTrimBoth lexbuf 2 2) } - | ('`' '`' (([^'`' '\n' '\r' '\t'] | ("`"[^'`' '\n' '\r' '\t']))+)'`'?) | "````" | "```" | "``" | "`" + | '`' '`' (([^'`' '\n' '\r' '\t'] | ('`' [^'`' '\n' '\r' '\t']))+)'`' { errorR(Error(FSComp.SR.lexInvalidIdentifier(), lexbuf.LexemeRange)) - RESERVED } + Keywords.IdentifierToken args lexbuf (lexemeTrimBoth lexbuf 2 1) } + + | '`' '`' (([^'`' '\n' '\r' '\t'] | ('`'[^'`' '\n' '\r' '\t']))+) + { errorR(Error(FSComp.SR.lexInvalidIdentifier(), lexbuf.LexemeRange)) + Keywords.IdentifierToken args lexbuf (lexemeTrimLeft lexbuf 2) } + + | "````" | "```" | "``" | "`" + { errorR(Error(FSComp.SR.lexInvalidIdentifier(), lexbuf.LexemeRange)) + Keywords.IdentifierToken args lexbuf "" } | ('#' anywhite* | "#line" anywhite+ ) digit+ anywhite* ('@'? "\"" [^'\n''\r''"']+ '"')? anywhite* newline { let pos = lexbuf.EndPos diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 0b9322188d0..367ca0c359a 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -5795,7 +5795,10 @@ nameop: identExpr: | ident - { SynExpr.Ident($1) } + { if $1.idText = "" then + SynExpr.FromParseError(SynExpr.Ident($1), $1.idRange) + else + SynExpr.Ident($1) } | opName { let m = lhs parseState diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl index 7cd4aaa32c4..7e4b6c613c6 100644 --- a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 01.fs.bsl @@ -5,76 +5,56 @@ ImplFile [SynModuleOrNamespace ([Module], false, NamedModule, [Expr - (Do - (ArbitraryAfterError ("unfinished identifier", (4,4--4,5)), - (3,0--4,5)), (3,0--4,5)); - Expr - (Do - (ArbitraryAfterError ("unfinished identifier", (7,4--7,7)), - (6,0--7,7)), (6,0--7,7)); + (Do (FromParseError (Ident , (4,4--4,5)), (3,0--4,5)), (3,0--4,5)); + Expr (Do (Ident , (6,0--7,7)), (6,0--7,7)); + Expr (Do (Ident ` , (9,0--10,8)), (9,0--10,8)); Expr - (Do - (ArbitraryAfterError ("unfinished identifier", (10,4--10,8)), - (9,0--10,8)), (9,0--10,8)); - Expr - (Do - (ArbitraryAfterError ("unfinished identifier", (13,4--13,8)), - (12,0--13,8)), (12,0--13,8)); - Expr (Do (Ident , (15,0--16,9)), (15,0--16,9)); + (Do (FromParseError (Ident , (13,4--13,8)), (12,0--13,8)), + (12,0--13,8)); Expr (Do (Ident , (15,0--16,9)), (15,0--16,9)); Expr (Do (App - (NonAtomic, false, - ArbitraryAfterError ("unfinished identifier", (19,4--19,5)), - ArbitraryAfterError ("unfinished identifier", (19,6--19,11)), - (19,4--19,11)), (18,0--19,11)), (18,0--19,11)); + (NonAtomic, false, FromParseError (Ident , (19,4--19,5)), + Ident ` , (19,4--19,11)), (18,0--19,11)), (18,0--19,11)); Expr (Do (App - (NonAtomic, false, - ArbitraryAfterError ("unfinished identifier", (22,4--22,5)), + (NonAtomic, false, FromParseError (Ident , (22,4--22,5)), Ident , (22,4--22,11)), (21,0--22,11)), (21,0--22,11)); Expr (Do (App - (NonAtomic, false, - ArbitraryAfterError ("unfinished identifier", (25,4--25,8)), - ArbitraryAfterError ("unfinished identifier", (25,8--25,12)), - (25,4--25,12)), (24,0--25,12)), (24,0--25,12)); + (NonAtomic, false, FromParseError (Ident , (25,4--25,8)), + FromParseError (Ident , (25,8--25,12)), (25,4--25,12)), + (24,0--25,12)), (24,0--25,12)); Expr (Do (App - (NonAtomic, false, - ArbitraryAfterError ("unfinished identifier", (28,4--28,8)), - ArbitraryAfterError ("unfinished identifier", (28,8--28,12)), - (28,4--28,12)), (27,0--28,12)), (27,0--28,12)); + (NonAtomic, false, FromParseError (Ident , (28,4--28,8)), + Ident ` , (28,4--28,12)), (27,0--28,12)), (27,0--28,12)); Expr (Do (App - (NonAtomic, false, - ArbitraryAfterError ("unfinished identifier", (31,4--31,8)), - ArbitraryAfterError ("unfinished identifier", (31,8--31,11)), - (31,4--31,11)), (30,0--31,11)), (30,0--31,11)); + (NonAtomic, false, FromParseError (Ident , (31,4--31,8)), + Ident , (31,4--31,11)), (30,0--31,11)), (30,0--31,11)); Expr (Do (App - (NonAtomic, false, - ArbitraryAfterError ("unfinished identifier", (34,4--34,8)), - ArbitraryAfterError ("unfinished identifier", (34,8--34,9)), - (34,4--34,9)), (33,0--34,9)), (33,0--34,9)); + (NonAtomic, false, FromParseError (Ident , (34,4--34,8)), + FromParseError (Ident , (34,8--34,9)), (34,4--34,9)), + (33,0--34,9)), (33,0--34,9)); Expr (Do (Ident ` , (36,0--37,10)), (36,0--37,10)); Expr (Do (App (NonAtomic, false, Ident ` , - ArbitraryAfterError - ("unfinished identifier", (40,10--40,11)), (40,4--40,11)), + FromParseError (Ident , (40,10--40,11)), (40,4--40,11)), (39,0--40,11)), (39,0--40,11)); Expr (Do (DotGet - (ArbitraryAfterError ("unfinished identifier", (43,4--43,8)), - (43,8--43,9), SynLongIdent ([P], [], [None]), (43,4--43,10)), + (FromParseError (Ident , (43,4--43,8)), (43,8--43,9), + SynLongIdent ([P], [], [None]), (43,4--43,10)), (42,0--43,10)), (42,0--43,10)); Expr (Do @@ -87,8 +67,7 @@ ImplFile SynLongIdent ([op_Addition], [], [Some (OriginalNotation "+")]), None, (46,6--46,7)), Const (Int32 1, (46,4--46,5)), - (46,4--46,7)), - ArbitraryAfterError ("unfinished identifier", (46,8--46,9)), + (46,4--46,7)), FromParseError (Ident , (46,8--46,9)), (46,4--46,9)), (45,0--46,9)), (45,0--46,9))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--46,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs new file mode 100644 index 00000000000..2ff5da44508 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs @@ -0,0 +1,6 @@ +module Module + +type T() = + member this.`() = () + + member this.````() = () diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl new file mode 100644 index 00000000000..a438cd85de0 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl @@ -0,0 +1,88 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Unfinished escaped ident 02.fs", false, + QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [T], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + ObjectModel + (Unspecified, + [ImplicitCtor + (None, [], SimplePats ([], (3,6--3,8)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None }); + Member + (SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (Some { IsInstance = true + IsDispatchSlot = false + IsOverrideOrExplicitImpl = false + IsFinal = false + GetterOrSetterIsCompilerGenerated = false + MemberKind = Member }, + SynValInfo + ([[SynArgInfo ([], false, None)]; []], + SynArgInfo ([], false, None)), None), + LongIdent + (SynLongIdent + ([this; ], [(4,15--4,16)], [None; None]), None, + None, + Pats + [Paren + (Const (Unit, (4,17--4,19)), (4,17--4,19))], + None, (4,11--4,19)), None, + Const (Unit, (4,22--4,24)), (4,11--4,19), + NoneAtInvisible, + { LeadingKeyword = Member (4,4--4,10) + InlineKeyword = None + EqualsRange = Some (4,20--4,21) }), (4,4--4,24)); + Member + (SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((6,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (Some { IsInstance = true + IsDispatchSlot = false + IsOverrideOrExplicitImpl = false + IsFinal = false + GetterOrSetterIsCompilerGenerated = false + MemberKind = Member }, + SynValInfo + ([[SynArgInfo ([], false, None)]; []], + SynArgInfo ([], false, None)), None), + LongIdent + (SynLongIdent + ([this; ], [(6,15--6,16)], [None; None]), None, + None, + Pats + [Paren + (Const (Unit, (6,20--6,22)), (6,20--6,22))], + None, (6,11--6,22)), None, + Const (Unit, (6,25--6,27)), (6,11--6,22), + NoneAtInvisible, + { LeadingKeyword = Member (6,4--6,10) + InlineKeyword = None + EqualsRange = Some (6,23--6,24) }), (6,4--6,27))], + (4,4--6,27)), [], + Some + (ImplicitCtor + (None, [], SimplePats ([], (3,6--3,8)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })), (3,5--6,27), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,9--3,10) + WithKeyword = None })], (3,0--6,27))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,27), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(4,16)-(4,17) parse error This is not a valid identifier +(6,16)-(6,20) parse error This is not a valid identifier diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs new file mode 100644 index 00000000000..49d18301d73 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs @@ -0,0 +1,9 @@ +module Module + +match () with +| ` -> () +| ```` -> () + +match () with +| `` -> () +| _ -> () \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs.bsl new file mode 100644 index 00000000000..683dccae609 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs.bsl @@ -0,0 +1,42 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Unfinished escaped ident 03.fs", false, + QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (Match + (Yes (3,0--3,13), Const (Unit, (3,6--3,8)), + [SynMatchClause + (Named (SynIdent (, 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) }); + SynMatchClause + (Named (SynIdent (, None), false, None, (5,2--5,6)), None, + Const (Unit, (5,10--5,12)), (5,2--5,12), Yes, + { ArrowRange = Some (5,7--5,9) + BarRange = Some (5,0--5,1) })], (3,0--5,12), + { MatchKeyword = (3,0--3,5) + WithKeyword = (3,9--3,13) }), (3,0--5,12)); + Expr + (Match + (Yes (7,0--7,13), Const (Unit, (7,6--7,8)), + [SynMatchClause + (Or + (Named + (SynIdent ( -> (), None), false, None, (8,2--8,10)), + Wild (9,2--9,3), (8,2--9,3), { BarRange = (9,0--9,1) }), + None, Const (Unit, (9,7--9,9)), (8,2--9,9), Yes, + { ArrowRange = Some (9,4--9,6) + BarRange = Some (8,0--8,1) })], (7,0--9,9), + { MatchKeyword = (7,0--7,5) + WithKeyword = (7,9--7,13) }), (7,0--9,9))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--9,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(4,2)-(4,3) parse error This is not a valid identifier +(5,2)-(5,6) parse error This is not a valid identifier +(8,2)-(8,10) parse error This is not a valid identifier From 7b04138c28e79114e0e3eb2ac70ffbb70d73caf6 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 5 Apr 2023 14:59:54 +0200 Subject: [PATCH 3/7] Update translations --- src/Compiler/xlf/FSComp.txt.cs.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.de.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.es.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.fr.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.it.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.ja.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.ko.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.pl.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.ru.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.tr.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 +++++ 13 files changed, 65 insertions(+) diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 2e4f6f33890..2606202fcf5 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -527,6 +527,11 @@ Oblasti IF-FSHARP/IF-CAML už nejsou podporovány. + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. Znak }} musí být v interpolovaném řetězci uvozený (zdvojeným znakem). diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 7fe4ec9b51b..f05a346748b 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -527,6 +527,11 @@ IF-FSHARP-/IF-CAML-Regionen werden nicht mehr unterstützt + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. Ein }}-Zeichen muss in einer interpolierten Zeichenfolge (durch Verdoppeln) mit Escapezeichen versehen werden. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 7e7b4216221..b2f71edb438 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -527,6 +527,11 @@ Ya no se admiten las regiones IF-FSHARP/IF-CAML + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. El carácter "}}" se debe escapar (duplicándose) en las cadenas interpoladas. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 7d70f3ba92e..81be76905d2 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -527,6 +527,11 @@ Les régions IF-FSHARP/IF-CAML ne sont plus prises en charge. + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. Un caractère '}}' doit faire l'objet d'une séquence d'échappement (par doublement) dans une chaîne interpolée. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index a57dc03a944..45902c8227a 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -527,6 +527,11 @@ Le aree IF-FSHARP/IF-CAML non sono più supportate + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. In una stringa interpolata è necessario specificare il carattere di escape di un carattere '}}' raddoppiandolo. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 84798fca490..4a36f5b9690 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -527,6 +527,11 @@ IF-FSHARP/IF-CAML リージョンは現在サポートされていません + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. 文字 '}}' は、補間された文字列内で (二重にすることで) エスケープする必要があります。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 3ee4e995c28..e2e0fccc72c 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -527,6 +527,11 @@ IF-FSHARP/IF-CAML 영역은 더 이상 지원되지 않습니다. + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. '}}' 문자는 보간된 문자열에서 이중으로 사용하여 이스케이프해야 합니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index f238950ca66..b5214a38659 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -527,6 +527,11 @@ Regiony IF-FSHARP/IF-CAML nie są już obsługiwane + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. W przypadku znaku „}}” należy zastosować ucieczkę (przez wpisanie dwóch takich znaków) w ciągu interpolowanym. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index f68e4bc8e6a..e89cfcdc0e1 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -527,6 +527,11 @@ As regiões IF-FSHARP/IF-CAML não são mais suportadas + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. Um caractere ''}}' precisa ser de escape (ao duplicar) em uma cadeia de caracteres interpolada. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 56c0cae8700..53b13bb6a3a 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -527,6 +527,11 @@ Регионы IF-FSHARP/IF-CAML больше не поддерживаются + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. Символ "}}" необходимо экранировать (путем дублирования) в интерполированной строке. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index f3935f23d5d..508be2e7ce7 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -527,6 +527,11 @@ IF-FSHARP/IF-CAML bölgeleri artık desteklenmiyor + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. Bir '}}' karakteri, düz metin arasına kod eklenmiş bir dizede kaçış dizisi ile (yineleme yapılarak) belirtilir. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 2795a7b7332..857db2c7925 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -527,6 +527,11 @@ 不再支持 IF-FSHARP/IF-CAML 区域 + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. 在内插字符串中,必需对 "}}" 字符进行转义(通过加倍)。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 6121684e880..feb5dc7f944 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -527,6 +527,11 @@ 不再支援 IF-FSHARP/IF-CAML 區域 + + This is not a valid identifier + This is not a valid identifier + + A '}}' character must be escaped (by doubling) in an interpolated string. 在插補字串中,必須將 '}}' 字元逸出 (重複一次)。 From 13b687940dbd83cd0f4f97192e53d8aaeb1a60f8 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 5 Apr 2023 15:01:59 +0200 Subject: [PATCH 4/7] Add newline to test data --- .../data/SyntaxTree/Expression/Unfinished escaped ident 03.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs index 49d18301d73..1dc96966990 100644 --- a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 03.fs @@ -6,4 +6,4 @@ match () with match () with | `` -> () -| _ -> () \ No newline at end of file +| _ -> () From 6ded4a92c0ee46207f7b070b880d009b4d9dcb4f Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 5 Apr 2023 15:33:15 +0200 Subject: [PATCH 5/7] Update test baselines --- .../ExceptionDefinitions/ExceptionDefinitions.fs | 2 +- .../DeclarationElements/LetBindings/Basic/Basic.fs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/ExceptionDefinitions/ExceptionDefinitions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/ExceptionDefinitions/ExceptionDefinitions.fs index fa91ce4572e..cf6b9e71f86 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/ExceptionDefinitions/ExceptionDefinitions.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/ExceptionDefinitions/ExceptionDefinitions.fs @@ -182,7 +182,7 @@ module ExceptionDefinition = |> compile |> shouldFail |> withDiagnostics [ - (Error 10, Line 7, Col 11, Line 7, Col 12, "Unexpected reserved keyword in exception definition. Expected identifier or other token.") + (Error 3563, Line 7, Col 11, Line 7, Col 17, "This is not a valid identifier") ] // SOURCE=E_DynamicInvocationNotSupported.fsx SCFLAGS=--test:ErrorRanges # E_DynamicInvocationNotSupported.fsx diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs index a357441a2f1..6d09e9320f2 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs @@ -89,10 +89,8 @@ module Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 10, Line 7, Col 13, Line 7, Col 14, "Unexpected reserved keyword in pattern") - (Error 583, Line 7, Col 8, Line 7, Col 9, "Unmatched '('") - (Error 10, Line 7, Col 25, Line 7, Col 26, "Unexpected reserved keyword in binding") - (Error 583, Line 7, Col 19, Line 7, Col 20, "Unmatched '('") + (Error 3563, Line 7, Col 13, Line 7, Col 14, "This is not a valid identifier") + (Error 3563, Line 7, Col 25, Line 7, Col 26, "This is not a valid identifier") ] // SOURCE=E_InvalidInnerRecursiveBinding.fs SCFLAGS="--test:ErrorRanges" # E_InvalidInnerRecursiveBinding.fs From f8008a7522282f9a63d2541d23315d1e57d8368c Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 5 Apr 2023 16:10:14 +0200 Subject: [PATCH 6/7] More baseline updates --- .../Conformance/UnionTypes/UnionTypes.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/UnionTypes/UnionTypes.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/UnionTypes/UnionTypes.fs index bd0382befeb..5ed40fe06b0 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/UnionTypes/UnionTypes.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/UnionTypes/UnionTypes.fs @@ -91,7 +91,7 @@ module UnionTypes = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 10, Line 9, Col 12, Line 9, Col 13, "Unexpected reserved keyword in union case. Expected identifier, '(', '(*)' or other token.") + (Error 3563, Line 9, Col 12, Line 9, Col 18, "This is not a valid identifier") ] //SOURCE=E_BeginWithUppercaseNoPipe01.fsx SCFLAGS="--test:ErrorRanges" # E_BeginWithUppercaseNoPipe01.fsx From 64e9a9cde0a0c350b9ce9a85f39c49c8f41a2d15 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 5 Apr 2023 18:34:35 +0200 Subject: [PATCH 7/7] Fix VisualFSharp test --- .../src/FSharp.Editor/Completion/CompletionUtils.fs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs index 3a2f4d81e98..0257d2425b4 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs @@ -159,8 +159,6 @@ module internal CompletionUtils = // If caret is at a backtick-identifier, then that is our span. // Else, check if we are after an unclosed ``, to support the common case of a manually typed leading ``. - // Tokenizer will not consider this an identifier, it will consider the bare `` a Keyword, followed by - // arbitrary tokens (Identifier, Operator, Text, etc.) depending on the trailing text. // Else, backticks are not involved in caret location, fall back to standard identifier character scan. @@ -176,8 +174,8 @@ module internal CompletionUtils = && Tokenizer.isDoubleBacktickIdent (sourceText.ToString(classifiedSpan.TextSpan)) let isUnclosedBacktick (classifiedSpan: ClassifiedSpan) = - classifiedSpan.ClassificationType = ClassificationTypeNames.Keyword - && sourceText.ToString(classifiedSpan.TextSpan) = "``" + classifiedSpan.ClassificationType = ClassificationTypeNames.Identifier + && sourceText.ToString(classifiedSpan.TextSpan).StartsWith "``" match classifiedSpans