Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,7 @@ public void visitPropertyExpression(final PropertyExpression expression) {
// GROOVY-8448: "this.name" from anon. inner class
if (fieldNode != null && !expression.isImplicitThis()
&& (fieldNode.getModifiers() & ACC_SYNTHETIC) != 0
&& fieldNode.getType().equals(ClassHelper.REFERENCE_TYPE)) {
/*&& fieldNode.getType().equals(ClassHelper.REFERENCE_TYPE)*/) {
fieldNode = null;
}
// GROOVY-10695: "this.name" or "Type.name" where "name" is non-static
Expand Down
30 changes: 15 additions & 15 deletions src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import static org.codehaus.groovy.transform.trait.Traits.isTrait;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
import static org.objectweb.asm.Opcodes.ACC_MANDATED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;

Expand Down Expand Up @@ -204,26 +204,26 @@ public void visitConstructorCallExpression(ConstructorCallExpression call) {
addFieldInit(thisParameter, thisField, block);
}

// for each shared variable, add a Reference field
for (Iterator<Variable> it = scope.getReferencedLocalVariablesIterator(); it.hasNext();) {
Variable var = it.next();

VariableExpression ve = new VariableExpression(var);
ve.setClosureSharedVariable(true);
ve.setUseReferenceDirectly(true);
// for each shared variable, add a field
for (Iterator<Variable> it = scope.getReferencedLocalVariablesIterator(); it.hasNext(); ) { Variable var = it.next();
var ve = new VariableExpression(var);
// ve.setClosureSharedVariable(true);
// ve.setUseReferenceDirectly(true);
expressions.add(pCount, ve);

ClassNode referenceType = ClassHelper.REFERENCE_TYPE.getPlainNodeReference();
Parameter p = new Parameter(referenceType, "p" + pCount);
// ClassNode referenceType = ClassHelper.REFERENCE_TYPE.getPlainNodeReference();
// Parameter p = new Parameter(referenceType, "p" + pCount);
var p = new Parameter(var.getType(), "p" + pCount);
p.setOriginType(var.getOriginType());
parameters.add(pCount++, p);

VariableExpression initial = new VariableExpression(p);
var initial = new VariableExpression(p);
initial.setSynthetic(true);
initial.setUseReferenceDirectly(true);
FieldNode pField = innerClass.addFieldFirst(ve.getName(), ACC_PUBLIC | ACC_SYNTHETIC, referenceType, initial);
pField.setHolder(true);
pField.setOriginType(ClassHelper.getWrapper(var.getOriginType()));
// initial.setUseReferenceDirectly(true);
FieldNode pField = innerClass.addFieldFirst(ve.getName(), ACC_PRIVATE | ACC_SYNTHETIC, p.getType(), initial);
// pField.setOriginType(ClassHelper.getWrapper(p.getOriginType()));
// pField.setOriginType(p.getOriginType());
// pField.setHolder(true);
}

innerClass.addConstructor(ACC_SYNTHETIC, parameters.toArray(Parameter.EMPTY_ARRAY), ClassNode.EMPTY_ARRAY, block);
Expand Down
60 changes: 0 additions & 60 deletions src/test/groovy/bugs/Groovy9120.groovy

This file was deleted.

37 changes: 35 additions & 2 deletions src/test/groovy/gls/innerClass/InnerClassTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ final class InnerClassTest {
}
assert a.call() == 1
x = 2
assert a.call() == 2
assert a.call() == 1
'''
}

Expand Down Expand Up @@ -215,6 +215,39 @@ final class InnerClassTest {
'''
}

// GROOVY-9120
@Test
void testAccessLocalVariableFromClosureInAIC2() {
assertScript '''
import java.util.concurrent.Callable

interface Face9120 {
Runnable runnable()
Callable<Long> callable()
}

static Face9120 make() {
final long number = 42
return new Face9120() {
@Override
Runnable runnable() {
return { ->
assert "number is ${number}" == 'number is 42'
}
}
@Override
Callable<Long> callable() {
return { -> number }
}
}
}

def face = make()
face.runnable().run()
assert "number is ${face.callable().call()}" == 'number is 42'
'''
}

// GROOVY-9825
@Test
void testAccessSuperInterfaceConstantWithInnerClass() {
Expand Down Expand Up @@ -1582,7 +1615,7 @@ final class InnerClassTest {
def v = false
def a = new A() {
@Override void m() {
assert v == true
assert !v
}
}
v = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ abstract class AbstractBytecodeTestCase extends GroovyTestCase {

@Override
protected void assertScript(final String script) throws Exception {
CompilationUnit unit = null
GroovyShell shell = new GroovyShell(new GroovyClassLoader() {
def array = new CompilationUnit[1]
def shell = new GroovyShell(new GroovyClassLoader() {
@Override
protected CompilationUnit createCompilationUnit(final CompilerConfiguration config, final CodeSource source) {
unit = super.createCompilationUnit(config, source)
array[0] = super.createCompilationUnit(config, source)
}
})
try {
shell.evaluate(script, testClassName)
} finally {
if (unit != null) {
if (array[0] instanceof CompilationUnit unit) {
try {
def firstClass = unit.classes.find { it.name == unit.firstClassNode.name }
sequence = extractSequence(firstClass.bytes, extractionOptions)
Expand Down Expand Up @@ -114,34 +114,36 @@ abstract class AbstractBytecodeTestCase extends GroovyTestCase {

InstructionSequence extractSequence(final byte[] bytes, final Map options = [method: 'run']) {
def out = new StringBuilderWriter()
def tcv
tcv = new TraceClassVisitor(new ClassVisitor(CompilerConfiguration.ASM_API_VERSION) {
Reference<TraceClassVisitor> ref = []
def tcv = new TraceClassVisitor(new ClassVisitor(CompilerConfiguration.ASM_API_VERSION) {
List getText() { ref.p.text }
@Override
MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String... exceptions) {
if (options.method == name) {
// last in "tcv.p.text" is a list that will be filled by "super.visit"
tcv.p.text.add(tcv.p.text.size() - 2, '--BEGIN--\n')
// last in "text" is a list that will be filled by "super.visit"
text.add(text.size() - 2, '--BEGIN--\n')
try {
super.visitMethod(access, name, desc, signature, exceptions)
} finally {
tcv.p.text.add('--END--\n')
text.add('--END--\n')
}
}
}
@Override
FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) {
if (options.field == name) {
// last in "tcv.p.text" is a list that will be filled by "super.visit"
tcv.p.text.add(tcv.p.text.size() - 2, '--BEGIN--\n')
// last in "text" is a list that will be filled by "super.visit"
text.add(text.size() - 2, '--BEGIN--\n')
try {
super.visitField(access, name, desc, signature, value)
} finally {
tcv.p.text.add('--END--\n')
text.add('--END--\n')
}
}
}
}, new PrintWriter(out))

ref.set(tcv)
new ClassReader(bytes).accept(tcv, 0)
new InstructionSequence(instructions: out.toString().split('\n')*.trim())
}
Expand Down
Loading