[
https://issues.apache.org/jira/browse/GROOVY-12514?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18132041#comment-18132041
]
ASF GitHub Bot commented on GROOVY-12514:
-----------------------------------------
codeconsole opened a new pull request, #3049:
URL: https://github.com/apache/groovy/pull/3049
This makes qualified `this` and `super` in nested classes (`N.this`,
`N.super`, `Outer.super`) work under `@TypeChecked` and `@CompileStatic` as in
Java. `Outer.super` from a closure or an inner class goes through the `super$`
helper methods that statically compiled closures use for `super` calls, so the
two bugs of those helpers that it runs into are fixed first: GROOVY-12516 and
GROOVY-12518. Each issue has its own commit (GROOVY-12514 one for `this` and
one for `super`, GROOVY-12518 two more, for overloaded setters and for
extension accessors).
These were split out of #3044, which keeps the private member fixes for
nested classes, and they build on it: GROOVY-12512 there makes `Outer.super`
without an enclosing instance (in a static nested class, or in an anonymous
class in a static method) a compile error in every mode, and the support for
`Outer.super` here relies on that check rather than repeating it. Until #3044
is merged, this pull request also shows its commits; the seven to review start
at "GROOVY-12514: STC: allow a qualified this that names the current nested
class".
Three cases combine this with other open pull requests, and the second of
each pair to be merged adds their tests:
- `Outer.super.sm()` for a static method that `Outer` hides needs
GROOVY-12519 (#3045), as `super.sm()` does;
- `Outer.super.x = v`, `++` and compound assignments with overloaded
setters, in dynamic Groovy and under `@TypeChecked`, need GROOVY-12521 (#3047),
as `super.x = v` does;
- `super.text += v` under `@TypeChecked`, where the accessors are extension
methods that the class overrides, needs GROOVY-12522 (#3048).
```groovy
class Base { String p() { 'base' } }
@CompileStatic
class Outer extends Base {
String p() { 'outer' }
static class N extends Base {
String p() { 'n' }
String test() { N.super.p() } // was "No such property: super";
now 'base' (GROOVY-12514)
}
class Inner {
String test() { Outer.super.p() } // was "No such property: super";
now 'base', on the enclosing instance (GROOVY-12517)
}
}
```
## GROOVY-12514: `N.this` and `N.super` within a nested class `N`
`N.this`, which is `this`, failed under `@TypeChecked` and `@CompileStatic`
with "No such property: this", and `N.super.m()` and `N.super.p` with "No such
property: super", in static nested, inner and enum classes and in closures and
lambdas there. Both now compile, as in javac. `N.super` means `super` in every
mode: dynamic Groovy read `N.super.p` as `N.this.p`. In a static context they
remain errors. `Top.this` and `Top.super` in a top-level class keep their error
(GROOVY-4321, `StaticThisTest`).
## GROOVY-12517: `Outer.super` in a class nested in `Outer`
In an inner class, an anonymous class, a closure or lambda in one of them,
or an inner class of an inner class, `Outer.super.m()` and `Outer.super.p`
failed under `@TypeChecked` and `@CompileStatic` with "No such property:
super". They now call the superclass's member on the enclosing `Outer`
instance, as in javac. Under `@CompileStatic` the calls go through `super$`
helper methods of `Outer`, since only `Outer` may call its superclass's methods
non-virtually. Property reads and writes, `++` and compound assignments work
too. Dynamic Groovy read and wrote `Outer.super.p` as `Outer.this.p`; it now
uses the superclass's property. Without an enclosing instance of `Outer` it
stays an error.
## GROOVY-12516 and GROOVY-12518: `super` in closures under `@CompileStatic`
- GROOVY-12516: two closures or lambdas of one class calling the same super
method generated the `super$` helper twice, and the class failed to load with
`ClassFormatError`. The helper is generated once.
- GROOVY-12518: `super.p`, `super.name` and `super.name = v` in a closure or
lambda failed with `VerifyError` (the superclass accessor was called with
`invokespecial` from the closure class); they now go through `super$` helpers,
like super method calls. `super.n++`, `++super.n` and `super.n += v` read the
property through a dynamic call that failed with `MissingPropertyException`
when the class declares the same property; they now call the superclass's
accessors. When the superclass overloads the setter (`setX(int)` and
`setX(String)`), the setter is the one the type checker selected for the value.
When an accessor is an extension method, such as `getText()` and
`setText(String)` of a `File`, `super.text += v` compiled to a dynamic property
access; it now calls the extension methods directly.
## Behaviour changes
Code that changes meaning in dynamic Groovy and under `@TypeChecked`, each
time to javac's meaning: `N.super.p` inside `N` reads the superclass's property
instead of `N.this.p` (GROOVY-12514); `Outer.super.p` and `Outer.super.f` in a
class nested in `Outer` use the superclass's member instead of `Outer.this`'s
(GROOVY-12517).
Code that failed to compile and now compiles: GROOVY-12514 and GROOVY-12517.
Code that failed at run time and now runs under `@CompileStatic`: GROOVY-12516
and GROOVY-12518.
## Tests
Each commit has tests that fail without it, marked with its JIRA key:
`gls.innerClass.InnerClassTest`, `ClosuresSTCTest` (and
`ClosuresStaticCompileTest`), `FieldsAndPropertiesSTCTest` (and
`FieldsAndPropertiesStaticCompileTest`) and, for the overloaded setters and the
extension accessors, `FieldsAndPropertiesStaticCompileTest` alone. 15,027 tests
in the `groovy`, `gls`, `bugs`, `org.codehaus.groovy.classgen`, `transform`,
`runtime`, `reflection`, `vmplugin`, `control` and `ast` packages and the stub
generator tests pass, apart from `bugs.Groovy12363`, which fails on master too
when it runs after `bugs.Groovy12142` in the same JVM (#3025 fixes it).
`groovy-contracts`, `groovy-typecheckers`, `groovy-ginq`,
`groovy-macro-library`, `groovy-json`, `groovy-xml` and `groovy-templates` pass
their tests, and every subproject compiles its main and test sources. The
Checkstyle and CodeNarc gates pass.
## Backport
GROOVY-12514 and GROOVY-12517 change what `N.super.p` and `Outer.super.p`
mean in dynamic Groovy, so whether to backport them is left to the maintainers;
GROOVY-12516 and GROOVY-12518 only make code that failed run.
> STC: qualified this or super naming the current nested class (N.this, N.super
> inside N) is rejected
> ---------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12514
> URL: https://issues.apache.org/jira/browse/GROOVY-12514
> Project: Groovy
> Issue Type: Bug
> Components: Compiler, Static Type Checker
> Affects Versions: 6.0.0
> Reporter: Scott Murphy Heiberg
> Priority: Major
>
> {{N.this}} inside a nested class {{N}} is {{this}}, and {{N.super.m()}} is
> {{super.m()}}. The type checker rejects both:
> {code:groovy}
> class Base { String m() { 'base' } }
> @groovy.transform.CompileStatic
> class Box {
> static class N extends Base {
> String id = 'n'
> String m() { 'n' }
> String test() { N.this.id + ' ' + N.super.m() }
> }
> }
> new Box.N().test()
> {code}
> {code}
> [Static type checking] - No such property: this for Class or static property
> for class: Box$N
> [Static type checking] - No such property: super for Class or static property
> for class: Box$N
> {code}
> (plus the errors that follow from them for {{id}} and {{m()}}). Dynamic
> Groovy returns {{n base}}, and javac accepts the same code. The same errors
> are reported under {{@TypeChecked}}, for an inner (non-static) class {{N}},
> for {{N.this.pm()}} and {{N.this.id = 'w'}}, for {{N.super.p}}, and inside a
> closure or lambda in {{N}}. {{N.this}} inside an anonymous class created in
> {{N}} already works, because {{N}} is an outer class there. Seen in 5.0.8,
> 6.0.0 and master.
> In a top-level class, {{Top.this}} and {{Top.super}} are rejected in every
> mode ("The usage of 'Class.this' and 'Class.super' is only allowed in
> nested/inner classes."), as GROOVY-4321 decided and {{StaticThisTest}} pins,
> so they are not part of this issue.
> Expected: under {{@TypeChecked}} and {{@CompileStatic}}, {{N.this}} and
> {{N.super}} inside the nested class {{N}} mean {{this}} and {{super}}, as in
> dynamic Groovy, except in a static context, where they stay an error.
> PR: https://github.com/apache/groovy/pull/3044
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)