[
https://issues.apache.org/jira/browse/GROOVY-12522?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18132040#comment-18132040
]
ASF GitHub Bot commented on GROOVY-12522:
-----------------------------------------
codeconsole opened a new pull request, #3048:
URL: https://github.com/apache/groovy/pull/3048
When a class declares its own version of an extension method of its
superclass, such as `first()` in an `ArrayList` subclass, `getProperties()`, or
`getText()` in a `File` subclass, `super.first()`, `super.properties` and
`super.getText()` in dynamic Groovy and under `@TypeChecked` threw
`MissingMethodException` or `MissingPropertyException`, or called
`getText(File, String)` with a null charset. Under `@CompileStatic`,
`super.text += v` compiles to a dynamic property access and failed the same
way. They now call the superclass's extension method, as they do when the class
does not declare one. This happens in 4.0.33 to master.
```groovy
class Numbers extends ArrayList<Integer> {
Numbers() { super([1, 2, 3]) }
Integer first() { -1 }
def test() { super.first() } // threw MissingMethodException; now 1
}
```
Split out of #3044.
## How
For `super` usage, the meta-class replaces a method the class declares with
the MOP method `super$N$name` of the superclass method it overrides, and drops
it when there is none. An extension method has no MOP method, so the class's
method was dropped, and the extension method it had replaced in the method
index was not restored. It now is: the extension method of the superclass, or
of an interface it implements, with the same parameters, the one for the most
specific type. The lookup is built once per class, by name.
## Tests
`groovy.ThisAndSuperTest`, in all three modes, and in a closure in dynamic
Groovy and under `@TypeChecked`. They fail without the change. Under
`@CompileStatic`, a `super` call to an extension method in a closure fails on
master for another reason, with `NoSuchMethodError`; GROOVY-12519 (#3045) fixes
that, so the closure case here runs in dynamic Groovy and under `@TypeChecked`
only. 14,936 tests in the `groovy`, `gls`, `bugs`,
`org.codehaus.groovy.classgen`, `transform`, `runtime`, `reflection`,
`vmplugin`, `control` and `ast` packages and the stub generator tests pass.
`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.
> super.name() and super.name miss an extension method that the class overrides
> -----------------------------------------------------------------------------
>
> Key: GROOVY-12522
> URL: https://issues.apache.org/jira/browse/GROOVY-12522
> Project: Groovy
> Issue Type: Bug
> Components: groovy-runtime
> Affects Versions: 6.0.0
> Reporter: Scott Murphy Heiberg
> Priority: Major
>
> When a class declares its own version of an extension method of its
> superclass, {{super.name()}} and {{super.name}} in dynamic Groovy and under
> {{@TypeChecked}} do not find the superclass's extension method:
> {code:groovy}
> class Numbers extends ArrayList<Integer> {
> Numbers() { super([1, 2, 3]) }
> Integer first() { -1 }
> def test() { super.first() }
> }
> class Bean {
> Map getProperties() { [:] }
> def test() { super.properties.containsKey('class') }
> }
> class Text extends File {
> Text(String path) { super(path) }
> String getText() { 'own' }
> def test() { [super.getText(), super.text] }
> }
> assert new Numbers().test() == 1 // fails: MissingMethodException: No
> signature of method: first for class: java.util.ArrayList
> assert new Bean().test() // fails: MissingPropertyException: No such
> property: properties for class: Bean
> def file = File.createTempFile('text', '.txt')
> file.text = 'content'
> assert new Text(file.path).test() == ['content', 'content'] // fails:
> NullPointerException: charsetName
> {code}
> {{super.getText()}} calls {{getText(File, String charset)}} with a null
> charset, the only {{getText}} left for {{super}}. Without the class's own
> method, all three work. Under {{@CompileStatic}} these calls work, but
> {{super.text += 'x'}} compiles to a dynamic property access and fails the
> same way. Seen in 4.0.33, 5.0.8, 6.0.0 and master.
> For {{super}}, a method the class declares is replaced by the MOP method
> {{super$2$name}} of the superclass method it overrides, or dropped when there
> is none. An extension method has no MOP method, so the class's method is
> dropped, and the extension method it replaced in the method index is not
> restored.
> Expected: {{super.name()}} and {{super.name}} call the superclass's extension
> method, as they do when the class does not declare the method.
> PR: https://github.com/apache/groovy/pull/3044
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)