[ 
https://issues.apache.org/jira/browse/GROOVY-12401?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Paul King closed GROOVY-12401.
------------------------------

> Improve remaining parser diagnostics and authored AST source positions
> ----------------------------------------------------------------------
>
>                 Key: GROOVY-12401
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12401
>             Project: Groovy
>          Issue Type: Improvement
>            Reporter: Daniel Sun
>            Assignee: Daniel Sun
>            Priority: Major
>             Fix For: 7.0.0-alpha-1, 6.0.0-RC-3
>
>
> h3. Problem
> After GROOVY-12353, several everyday syntax mistakes still surface as generic 
> *Unexpected input*, and several authored AST nodes still carry line/column 
> {{-1}} even though they came from source. Tooling uses {{lineNumber > 0}} to 
> tell authored code from generated code ({{SecureASTCustomizer.isFromSource}}).
> h3. Diagnostics (before)
> * Array creation without a size, an extra empty dimension, or a size combined 
> with an initializer:
> {noformat}
> new int[]
> new int[][2]
> new int[2] { 1 }
> {noformat}
> reports *Unexpected input*.
> * A type argument list written as a comparison (meant {noformat}List<Integer> 
> name{noformat}):
> {noformat}
> List<Integer name
> {noformat}
> reports *Unexpected input*.
> * A method header in a statement position (for example inside a closure 
> invoked as a statement) reports *Unexpected input* instead of naming the 
> misplaced method.
> * {{import}} inside a method reports {{Unexpected input: 'import'}}.
> * {{do}} with two statements and a later {{while}}:
> {noformat}
> do
> println 1
> println 2
> while (false)
> {noformat}
> reports {{Missing 'while'}} on the second {{println}} even though {{while}} 
> is already on the next line.
> * Enum constants followed by members without a semicolon:
> {noformat}
> enum E { A
>     void m() {}
> }
> {noformat}
> reports *Unexpected input* instead of asking for {{;}} after the last 
> constant.
> * An extra closer or semicolon reports {{Unexpected input: ')'}} (or the 
> matching {{]}} / {{\}}} / {{;}}) instead of naming the extra token.
> * A second {{default}} in a switch points the caret at the first {{default}}, 
> not the duplicate.
> * Integer overflow wording does not match javac's {{Integer number too 
> large}}.
> h3. Source positions (before)
> At CONVERSION these authored nodes dump as {{-1}}:
> * Interface field {{int a;}} — {{FieldNode.lastLineNumber}} is copied from a 
> synthetic {{ConstantExpression(0)}}. 
> {{DefaultGroovyMethods.asBoolean(Object)}} is non-null, so the synthetic 
> value is treated as a real stop.
> * Classic for-control {noformat}for (int i = 0; i < n; i++){noformat} — the 
> outer {{ClosureListExpression}} is never given a source span. Empty 
> init/cond/update slots ({{EmptyExpression.INSTANCE}}) should stay {{-1}}.
> * Authored empty parentheses:
> {noformat}
> new Object()
> new Runnable() { }
> super()
> {noformat}
> * GROOVY-11492 annotation default — the {{listX}} rewrite drops the brace 
> span:
> {noformat}
> String[] x() default { }
> {noformat}
> * Single-spread index wrapper (the multi-index path was already stamped):
> {noformat}
> a[*[1, 2]]
> {noformat}
> Not a bug — these have no span in the source and should stay {{-1}}: 
> {{ModuleNode}}, a script's wrapping {{BlockStatement}}, implicit {{return 
> null}}, TWR desugaring (names such as {noformat}__$$t0{noformat}), synthetic 
> {{@Trait}}, the class initializer {noformat}<clinit>{noformat}, and 
> {{EmptyExpression.INSTANCE}}.
> h3. Goal
> * javac-aligned sentences for the remaining recognition failures, with the 
> caret on the right token
> * authored AST nodes carry a real source span; generated nodes stay at {{-1}}
> * error-path only — no grammar error alternatives (GROOVY-9588)
> h3. Approach
> * {{AbstractFriendlyErrorStrategy}} refines the fallback sentence: array 
> creation, unclosed type argument, method header in statement position, 
> misplaced {{import}}, unmatched {{do}}/{{while}}, enum semicolon, extra 
> closers, annotation-style {{default}} after a method header. 
> {{MissingDelimiterDiagnostic}} still relocates the caret for an unclosed 
> {{)}} / {{]}} / {{\}}}. Locate/refine stay in a defensive try; listener 
> dispatch is one call afterwards.
> * {{AstBuilder}} / {{ModifierManager}} / {{Numbers}}: record headers, missing 
> method body vs abstract, index used as a method call, overflow wording; 
> duplicate {{default}} points at the second {{default}}.
> * {{PositionConfigureUtils}}: copy an end position only when {{lastLineNumber 
> > 0}}. Stamp the classic-for control list, authored empty parentheses, the 
> GROOVY-11492 {{listX}} result, and the single-spread index wrapper.
> h3. Expected result (after)
> * {noformat}new int[]{noformat} → {noformat}Array dimension missing; specify 
> a size or add an initializer '{}'{noformat}
> * {noformat}List<Integer name{noformat} → {{Missing '>'}}
> * method header in a statement position → {{Method definition not expected 
> here}}
> * {{import}} inside a method → {{'import' is only allowed at the beginning of 
> a compilation unit}}
> * {{do}} / two statements / later {{while}} → {noformat}do-while body must be 
> a single statement; wrap multiple statements in '{ }'{noformat}; a true 
> omission is still {{Missing 'while'}}
> * enum constants then members, no semicolon → {{';' expected after the last 
> enum constant}}
> * extra {{)}} → {{Unexpected ')'}}
> * interface {{int a;}}, empty {noformat}for (;;) { }{noformat}, {{new 
> Object()}}, annotation {noformat}default { }{noformat}, and {noformat}a[*[1, 
> 2]]{noformat} carry real line/column on the authored node; synthetic children 
> stay {{-1}}
> Valid programs are unchanged.
> h3. Related
> GROOVY-12353, GROOVY-11492, GROOVY-12169, GROOVY-9588



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to