| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.codehaus.groovy |
| |
| import groovy.test.GroovyTestCase |
| import org.codehaus.groovy.control.CompilationUnit |
| import org.codehaus.groovy.classgen.GeneratorContext |
| import org.codehaus.groovy.control.SourceUnit |
| import org.codehaus.groovy.control.Phases |
| import org.codehaus.groovy.ast.ClassNode |
| |
| /** |
| * Before Groovy 1.8, the structure of closure's inner classes |
| * was a bit different than it is now in 1.8+. |
| * |
| * This test checks that closure inner classes are direct child of their enclosing class, |
| * instead of being child of the outermost class. |
| */ |
| class ClosureAndInnerClassNodeStructureTest extends GroovyTestCase { |
| |
| void testStructure() { |
| def cu = new CompilationUnit() |
| cu.addSource("t.groovy", ''' |
| exec { // t$_run_closure1 |
| def d = { // t$_run_closure1$_closure3 |
| def o = new Object() { // t$1 |
| void run() { // |
| def f = {} // t$1$_run_closure1 |
| } // |
| } // |
| def e = {} // t$_run_closure1$_closure3$_closure4 |
| } // |
| } // |
| def g = {} // t$_run_closure2 |
| ''') |
| |
| def classNodes = [:] |
| |
| cu.addPhaseOperation(new CompilationUnit.IPrimaryClassNodeOperation() { |
| @Override |
| void call(SourceUnit source, GeneratorContext context, ClassNode cn) { |
| def recurse = { ClassNode node -> |
| classNodes[node.name] = node |
| for (icn in node.innerClasses) { |
| classNodes[icn.name] == icn |
| call(icn) |
| } |
| } |
| recurse(cn) |
| } |
| }, Phases.CLASS_GENERATION) |
| |
| cu.compile(Phases.CLASS_GENERATION) |
| |
| def assertParentOf = { String child -> |
| [isClass: { String parent -> |
| assert classNodes[child].outerClass.name == parent |
| }] |
| } |
| |
| assertParentOf 't$1' isClass 't' |
| assertParentOf 't$1$_run_closure1' isClass 't$1' |
| assertParentOf 't$_run_closure1' isClass 't' |
| assertParentOf 't$_run_closure2' isClass 't' |
| assertParentOf 't$_run_closure1$_closure3' isClass 't$_run_closure1' |
| assertParentOf 't$_run_closure1$_closure3$_closure4' isClass 't$_run_closure1$_closure3' |
| } |
| |
| // GROOVY-5351 |
| void testGetSimpleName() { |
| assertScript ''' |
| class X { |
| static class Y { |
| def foo() { |
| def cl = {return{}} |
| def cl2 = cl() |
| [cl.getClass().getSimpleName(), cl2.getClass().getSimpleName()] |
| } |
| } |
| } |
| def simpleNames = new X.Y().foo() |
| assert simpleNames == ['_foo_closure1', '_closure2'] |
| ''' |
| } |
| |
| //GROOVY-7119 && GROOVY-7120 |
| void testIrregularMethodName() { |
| assertScript ''' |
| class X { |
| def 'foo!bar'() { |
| return {} |
| } |
| } |
| def str = new X().'foo!bar'().getClass().getName() |
| assert str == 'X$_foo_bar_closure1' |
| ''' |
| } |
| } |