Skip to content

Commit d1ca485

Browse files
authored
LexFilter: rework wrong indentation recovery (#15334)
* LexFilter: better debug diagnostics * LexFilter: strict indentation for existing warnings * Update xlf * Signature generation: fix 'end' indentation in empty modules * Update baselines * Update baselines * Try to undo range change
1 parent 0cb3300 commit d1ca485

File tree

186 files changed

+2619
-326
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

186 files changed

+2619
-326
lines changed

src/Compiler/Checking/NicePrint.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2511,7 +2511,7 @@ module InferredSigPrinting =
25112511
else
25122512
// OK, this is a nested module, with indentation
25132513
if isEmptyL basic then
2514-
((modNameEqualsL ^^ wordL (tagKeyword"begin")) @@* basic) @@ WordL.keywordEnd
2514+
modNameEqualsL ^^ wordL (tagKeyword "begin") @@* basic @@* WordL.keywordEnd
25152515
else
25162516
modNameEqualsL @@* basic
25172517
layoutXmlDoc denv true mspec.XmlDoc basicL

src/Compiler/FSComp.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,7 @@ featureNestedCopyAndUpdate,"Nested record field copy-and-update"
15741574
featureExtendedStringInterpolation,"Extended string interpolation similar to C# raw string literals."
15751575
featureWarningWhenMultipleRecdTypeChoice,"Raises warnings when multiple record type matches were found during name resolution because of overlapping field names."
15761576
featureImprovedImpliedArgumentNames,"Improved implied argument names"
1577+
featureStrictIndentation,"Raises errors on incorrect indentation, allows better recovery and analysis during editing"
15771578
3353,fsiInvalidDirective,"Invalid directive '#%s %s'"
15781579
3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
15791580
3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
@@ -1663,7 +1664,7 @@ reprStateMachineInvalidForm,"The state machine has an unexpected form"
16631664
3521,tcInvalidMemberDeclNameMissingOrHasParen,"Invalid member declaration. The name of the member is missing or has parentheses."
16641665
3522,tcAnonRecdDuplicateFieldId,"The field '%s' appears multiple times in this record expression."
16651666
3523,tcAnonRecdTypeDuplicateFieldId,"The field '%s' appears multiple times in this anonymous record type."
1666-
3524,parsExpectingExpressionInTuple,"Expecting expression"
1667+
3524,parsExpectingExpression,"Expecting expression"
16671668
3530,tcTraitIsStatic,"Trait '%s' is static"
16681669
3531,tcTraitIsNotStatic,"Trait '%s' is not static"
16691670
3532,tcTraitMayNotUseComplexThings,"A trait may not specify optional, in, out, ParamArray, CallerInfo or Quote arguments"

src/Compiler/Facilities/LanguageFeatures.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type LanguageFeature =
2020
| WildCardInForLoop
2121
| RelaxWhitespace
2222
| RelaxWhitespace2
23+
| StrictIndentation
2324
| NameOf
2425
| ImplicitYield
2526
| OpenTypeDeclaration
@@ -163,6 +164,7 @@ type LanguageVersion(versionText) =
163164
LanguageFeature.WarningWhenMultipleRecdTypeChoice, previewVersion
164165
LanguageFeature.ImprovedImpliedArgumentNames, previewVersion
165166
LanguageFeature.DiagnosticForObjInference, previewVersion
167+
LanguageFeature.StrictIndentation, previewVersion
166168

167169
]
168170

@@ -288,6 +290,7 @@ type LanguageVersion(versionText) =
288290
| LanguageFeature.WarningWhenMultipleRecdTypeChoice -> FSComp.SR.featureWarningWhenMultipleRecdTypeChoice ()
289291
| LanguageFeature.ImprovedImpliedArgumentNames -> FSComp.SR.featureImprovedImpliedArgumentNames ()
290292
| LanguageFeature.DiagnosticForObjInference -> FSComp.SR.featureInformationalObjInferenceDiagnostic ()
293+
| LanguageFeature.StrictIndentation -> FSComp.SR.featureStrictIndentation ()
291294

292295
/// Get a version string associated with the given feature.
293296
static member GetFeatureVersionString feature =

src/Compiler/Facilities/LanguageFeatures.fsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type LanguageFeature =
1010
| WildCardInForLoop
1111
| RelaxWhitespace
1212
| RelaxWhitespace2
13+
| StrictIndentation
1314
| NameOf
1415
| ImplicitYield
1516
| OpenTypeDeclaration

src/Compiler/Facilities/prim-lexing.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ type internal Position =
154154
member x.ApplyLineDirective(fileIdx, line) =
155155
Position(fileIdx, line, x.OriginalLine, x.AbsoluteOffset, x.AbsoluteOffset)
156156

157+
override p.ToString() = $"({p.Line},{p.Column})"
158+
157159
static member Empty = Position()
158160

159161
static member FirstLine fileIdx = Position(fileIdx, 1, 0, 0, 0)

src/Compiler/SyntaxTree/LexFilter.fs

Lines changed: 94 additions & 50 deletions
Large diffs are not rendered by default.

src/Compiler/pars.fsy

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,7 +1727,9 @@ classDefnMembersAtLeastOne:
17271727
| classDefnMember opt_seps classDefnMembers
17281728
{ match $1, $3 with
17291729
| [ SynMemberDefn.Interface(members=Some []; range=m) ], nextMember :: _ ->
1730-
warning(IndentationProblem(FSComp.SR.lexfltTokenIsOffsideOfContextStartedEarlier(warningStringOfPos m.Start), nextMember.Range))
1730+
let strictIndentation = parseState.LexBuffer.SupportsFeature LanguageFeature.StrictIndentation
1731+
let warnF = if strictIndentation then errorR else warning
1732+
warnF(IndentationProblem(FSComp.SR.lexfltTokenIsOffsideOfContextStartedEarlier(warningStringOfPos m.Start), nextMember.Range))
17311733
| _ -> ()
17321734
$1 @ $3 }
17331735

@@ -2712,8 +2714,7 @@ hardwhiteDoBinding:
27122714
| ODO typedSequentialExprBlock hardwhiteDefnBindingsTerminator
27132715
{ let mDo = rhs parseState 1
27142716
let _, _, mDone = $3
2715-
let mEnd = match mDone with Some m -> m | _ -> $2.Range
2716-
let mAll = unionRanges mDo mEnd
2717+
let mAll = unionRanges mDo $2.Range
27172718
let seqPt = DebugPointAtBinding.NoneAtDo
27182719
// any attributes prior to the 'let' are left free, e.g. become top-level attributes
27192720
// associated with the module, 'main' function or assembly depending on their target
@@ -3531,6 +3532,11 @@ typedSequentialExprBlock:
35313532
{ if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileExpression())
35323533
exprFromParseError $2 }
35333534

3535+
| OBLOCKBEGIN oblockend
3536+
{ let m = rhs parseState 1
3537+
reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectingExpression ())
3538+
arbExpr ("typedSequentialExprBlock1", m.EndRange) }
3539+
35343540
| typedSequentialExpr
35353541
{ $1 }
35363542

@@ -3539,6 +3545,11 @@ declExprBlock:
35393545
| OBLOCKBEGIN typedSequentialExpr oblockend
35403546
{ $2 }
35413547

3548+
| OBLOCKBEGIN oblockend
3549+
{ let m = rhs parseState 1
3550+
reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectingExpression ())
3551+
arbExpr ("declExprBlock1", m.EndRange) }
3552+
35423553
| declExpr
35433554
{ $1 }
35443555

@@ -3552,7 +3563,7 @@ typedSequentialExprBlockR:
35523563
{ fun _ -> $1 }
35533564

35543565
| recover
3555-
{ fun mStart -> arbExpr ("typedSequentialExprBlockR", mStart) }
3566+
{ fun (mStart: range) -> arbExpr ("typedSequentialExprBlockR1", mStart.EndRange) }
35563567

35573568
typedSequentialExpr:
35583569
| sequentialExpr COLON typeWithTypeConstraints
@@ -3656,7 +3667,7 @@ declExpr:
36563667

36573668
| hardwhiteDoBinding %prec expr_let
36583669
{ let (BindingSetPreAttrs(_, _, _, _, m)), e = $1
3659-
SynExpr.Do(e, m) }
3670+
SynExpr.Do(e, unionRanges (rhs parseState 1).StartRange e.Range) }
36603671

36613672
| anonMatchingExpr %prec expr_function
36623673
{ $1 }
@@ -3720,6 +3731,42 @@ declExpr:
37203731
WithToEndRange = mWhole }
37213732
SynExpr.TryWith(expr, [], mWhole, spTry, spWith, trivia) }
37223733

3734+
| TRY ORIGHT_BLOCK_END %prec expr_try
3735+
{ let mTry = rhs parseState 1
3736+
let mExpr = mTry.EndRange
3737+
let expr = arbExpr ("try1", mExpr)
3738+
let spTry = DebugPointAtTry.Yes mTry
3739+
let mWith, (clauses, mLast) = mExpr, ([], mExpr)
3740+
reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectingExpression ())
3741+
let spWith = DebugPointAtWith.Yes mWith
3742+
let mTryToWith = unionRanges mTry mWith
3743+
let mWithToLast = unionRanges mWith mLast
3744+
let mTryToLast = unionRanges mTry mLast
3745+
let trivia: SynExprTryWithTrivia =
3746+
{ TryKeyword = mTry
3747+
TryToWithRange = mTryToWith
3748+
WithKeyword = mWith
3749+
WithToEndRange = mWithToLast }
3750+
SynExpr.TryWith(expr, clauses, mTryToLast, spTry, spWith, trivia) }
3751+
3752+
| TRY ORIGHT_BLOCK_END withClauses %prec expr_try
3753+
{ let mTry = rhs parseState 1
3754+
let mExpr = mTry.EndRange
3755+
let expr = arbExpr ("try2", mExpr)
3756+
let spTry = DebugPointAtTry.Yes mTry
3757+
let mWith, (clauses, mLast) = $3
3758+
reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectingExpression ())
3759+
let spWith = DebugPointAtWith.Yes mWith
3760+
let mTryToWith = unionRanges mTry mWith
3761+
let mWithToLast = unionRanges mWith mLast
3762+
let mTryToLast = unionRanges mTry mLast
3763+
let trivia: SynExprTryWithTrivia =
3764+
{ TryKeyword = mTry
3765+
TryToWithRange = mTryToWith
3766+
WithKeyword = mWith
3767+
WithToEndRange = mWithToLast }
3768+
SynExpr.TryWith(expr, clauses, mTryToLast, spTry, spWith, trivia) }
3769+
37233770
| TRY typedSequentialExprBlockR FINALLY typedSequentialExprBlock %prec expr_try
37243771
{ let mTry = rhs parseState 1
37253772
let tryExpr = $2 mTry
@@ -4233,6 +4280,11 @@ withClauses:
42334280
{ if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWith())
42344281
rhs parseState 1, $2 }
42354282

4283+
| OWITH recover
4284+
{ let mWith = rhs parseState 1
4285+
if not $2 then reportParseErrorAt mWith (FSComp.SR.parsUnexpectedEndOfFileWith ())
4286+
mWith, ([], mWith.EndRange) }
4287+
42364288
withPatternClauses:
42374289
| patternClauses
42384290
{ $1 None }
@@ -4338,21 +4390,13 @@ ifExprThen:
43384390
{ let mThen = rhs parseState 1
43394391
arbExpr ("ifThen1", mThen.EndRange), mThen }
43404392

4341-
| OTHEN OBLOCKBEGIN typedSequentialExpr oblockend %prec prec_then_if
4342-
{ $3, rhs parseState 1 }
4343-
4344-
| OTHEN OBLOCKBEGIN typedSequentialExpr recover %prec prec_then_if
4345-
{ if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileThen())
4346-
exprFromParseError $3, rhs parseState 1 }
4393+
| OTHEN typedSequentialExprBlock %prec prec_then_if
4394+
{ $2, rhs parseState 1 }
43474395

43484396
| OTHEN recover %prec prec_then_if
43494397
{ let mThen = rhs parseState 1
43504398
arbExpr ("ifThen2", mThen.EndRange), mThen }
43514399

4352-
| OTHEN OBLOCKBEGIN recover %prec prec_then_if
4353-
{ let mThen = rhs parseState 1
4354-
arbExpr ("ifThen3", mThen.EndRange), mThen }
4355-
43564400
ifExprElifs:
43574401
| /* EMPTY */
43584402
{ None, None }
@@ -4361,14 +4405,9 @@ ifExprElifs:
43614405
{ let mElse = rhs parseState 1
43624406
Some mElse, Some $2 }
43634407

4364-
| OELSE OBLOCKBEGIN typedSequentialExpr oblockend
4365-
{ let mElse = rhs parseState 1
4366-
Some mElse, Some $3 }
4367-
4368-
| OELSE OBLOCKBEGIN typedSequentialExpr recover
4408+
| OELSE typedSequentialExprBlock
43694409
{ let mElse = rhs parseState 1
4370-
if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileElse())
4371-
Some mElse, Some(exprFromParseError $3) }
4410+
Some mElse, Some $2 }
43724411

43734412
| ELIF declExpr ifExprCases
43744413
{ let mElif = rhs parseState 1
@@ -4400,15 +4439,15 @@ tupleExpr:
44004439
{ let exprs, commas = $1
44014440
let mComma1 = rhs parseState 2
44024441
let mComma2 = rhs parseState 3
4403-
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ())
4442+
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpression ())
44044443
let expr = arbExpr ("tupleExpr2", mComma1.EndRange)
44054444
$4 :: expr :: exprs, (mComma2 :: mComma1 :: commas) }
44064445

44074446
| tupleExpr COMMA COMMA ends_coming_soon_or_recover
44084447
{ let exprs, commas = $1
44094448
let mComma1 = rhs parseState 2
44104449
let mComma2 = rhs parseState 3
4411-
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ())
4450+
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpression ())
44124451
if not $4 then reportParseErrorAt mComma2 (FSComp.SR.parsExpectedExpressionAfterToken ())
44134452
let expr1 = arbExpr ("tupleExpr3", mComma1.EndRange)
44144453
let expr2 = arbExpr ("tupleExpr4", mComma2.EndRange)
@@ -4425,7 +4464,7 @@ tupleExpr:
44254464
| declExpr COMMA COMMA ends_coming_soon_or_recover
44264465
{ let mComma1 = rhs parseState 2
44274466
let mComma2 = rhs parseState 3
4428-
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ())
4467+
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpression ())
44294468
if not $4 then reportParseErrorAt mComma2 (FSComp.SR.parsExpectedExpressionAfterToken ())
44304469
let expr1 = arbExpr ("tupleExpr6", mComma1.EndRange)
44314470
let expr2 = arbExpr ("tupleExpr7", mComma2.EndRange)
@@ -4434,7 +4473,7 @@ tupleExpr:
44344473
| declExpr COMMA COMMA declExpr
44354474
{ let mComma1 = rhs parseState 2
44364475
let mComma2 = rhs parseState 3
4437-
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ())
4476+
reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpression ())
44384477
let expr = arbExpr ("tupleExpr8", mComma1.EndRange)
44394478
[$4; expr; $1], [mComma2; mComma1] }
44404479

src/Compiler/xlf/FSComp.txt.cs.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@
407407
<target state="translated">Statické členy v rozhraních</target>
408408
<note />
409409
</trans-unit>
410+
<trans-unit id="featureStrictIndentation">
411+
<source>Raises errors on incorrect indentation, allows better recovery and analysis during editing</source>
412+
<target state="new">Raises errors on incorrect indentation, allows better recovery and analysis during editing</target>
413+
<note />
414+
</trans-unit>
410415
<trans-unit id="featureStringInterpolation">
411416
<source>string interpolation</source>
412417
<target state="translated">interpolace řetězce</target>
@@ -792,9 +797,9 @@
792797
<target state="translated">Za tímto bodem byl očekáván vzor</target>
793798
<note />
794799
</trans-unit>
795-
<trans-unit id="parsExpectingExpressionInTuple">
800+
<trans-unit id="parsExpectingExpression">
796801
<source>Expecting expression</source>
797-
<target state="translated">Byl očekáván výraz.</target>
802+
<target state="new">Expecting expression</target>
798803
<note />
799804
</trans-unit>
800805
<trans-unit id="parsExpectingPatternInTuple">

src/Compiler/xlf/FSComp.txt.de.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@
407407
<target state="translated">Statische Member in Schnittstellen</target>
408408
<note />
409409
</trans-unit>
410+
<trans-unit id="featureStrictIndentation">
411+
<source>Raises errors on incorrect indentation, allows better recovery and analysis during editing</source>
412+
<target state="new">Raises errors on incorrect indentation, allows better recovery and analysis during editing</target>
413+
<note />
414+
</trans-unit>
410415
<trans-unit id="featureStringInterpolation">
411416
<source>string interpolation</source>
412417
<target state="translated">Zeichenfolgeninterpolation</target>
@@ -792,9 +797,9 @@
792797
<target state="translated">Nach diesem Punkt wurde ein Muster erwartet.</target>
793798
<note />
794799
</trans-unit>
795-
<trans-unit id="parsExpectingExpressionInTuple">
800+
<trans-unit id="parsExpectingExpression">
796801
<source>Expecting expression</source>
797-
<target state="translated">Ausdruck wird erwartet</target>
802+
<target state="new">Expecting expression</target>
798803
<note />
799804
</trans-unit>
800805
<trans-unit id="parsExpectingPatternInTuple">

src/Compiler/xlf/FSComp.txt.es.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@
407407
<target state="translated">Miembros estáticos en interfaces</target>
408408
<note />
409409
</trans-unit>
410+
<trans-unit id="featureStrictIndentation">
411+
<source>Raises errors on incorrect indentation, allows better recovery and analysis during editing</source>
412+
<target state="new">Raises errors on incorrect indentation, allows better recovery and analysis during editing</target>
413+
<note />
414+
</trans-unit>
410415
<trans-unit id="featureStringInterpolation">
411416
<source>string interpolation</source>
412417
<target state="translated">interpolación de cadena</target>
@@ -792,9 +797,9 @@
792797
<target state="translated">Se esperaba un patrón después de este punto</target>
793798
<note />
794799
</trans-unit>
795-
<trans-unit id="parsExpectingExpressionInTuple">
800+
<trans-unit id="parsExpectingExpression">
796801
<source>Expecting expression</source>
797-
<target state="translated">Se espera una expresión</target>
802+
<target state="new">Expecting expression</target>
798803
<note />
799804
</trans-unit>
800805
<trans-unit id="parsExpectingPatternInTuple">

0 commit comments

Comments
 (0)