Repository: groovy Updated Branches: refs/heads/master 4ea1207f2 -> 4bca3fea6
GROOVY-7967: AstNodeToScriptAdapter should output source using the recommended modifier order (closes #447) Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/4bca3fea Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/4bca3fea Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/4bca3fea Branch: refs/heads/master Commit: 4bca3fea67b9ed575725fa850c4f91884747cb61 Parents: 4ea1207 Author: paulk <pa...@asert.com.au> Authored: Tue Oct 11 20:50:48 2016 +1000 Committer: paulk <pa...@asert.com.au> Committed: Wed Oct 12 20:34:44 2016 +1000 ---------------------------------------------------------------------- .../swingui/AstNodeToScriptAdapter.groovy | 83 ++++-------- .../swingui/AstNodeToScriptAdapterTest.groovy | 133 +++++++++++-------- 2 files changed, 100 insertions(+), 116 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/4bca3fea/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstNodeToScriptAdapter.groovy ---------------------------------------------------------------------- diff --git a/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstNodeToScriptAdapter.groovy b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstNodeToScriptAdapter.groovy index 533abb4..083adcf 100644 --- a/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstNodeToScriptAdapter.groovy +++ b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstNodeToScriptAdapter.groovy @@ -18,7 +18,6 @@ */ package groovy.inspect.swingui - import org.codehaus.groovy.ast.* import org.codehaus.groovy.ast.expr.* import org.codehaus.groovy.ast.stmt.* @@ -37,10 +36,8 @@ import org.codehaus.groovy.classgen.Verifier * This class takes Groovy source code, compiles it to a specific compile phase, and then decompiles it * back to the groovy source. It is used by GroovyConsole's AST Browser, but can also be invoked from * the command line. - * - * @author Hamlet D'Arcy */ -class AstNodeToScriptAdapter { +class AstNodeToScriptAdapter { /** * Run this class as a script to compile a groovy file and print out the resulting source. @@ -68,20 +65,21 @@ and [compilephase] is a valid Integer based org.codehaus.groovy.control.CompileP } /** - * This method takes source code, compiles it, then reverses it back to source. - * @param script - * the source code to be compiled. If invalid, a compile error occurs - * @param compilePhase - * the CompilePhase. Must be an int mapped in {@link CompilePhase} - * @param classLoader - * (optional) the classloader to use. If missing/null then the current is used. - * This parameter enables things like ASTBrowser to invoke this with the correct classpath - * @param showScriptFreeForm - * Whether or not to show the script portion of the source code - * @param showScriptClass - * Whether or not to show the Script class from the source code - * @returns the source code from the AST state - */ + * This method takes source code, compiles it, then reverses it back to source. + * + * @param script + * the source code to be compiled. If invalid, a compile error occurs + * @param compilePhase + * the CompilePhase. Must be an int mapped in {@link CompilePhase} + * @param classLoader + * (optional) the classloader to use. If missing/null then the current is used. + * This parameter enables things like ASTBrowser to invoke this with the correct classpath + * @param showScriptFreeForm + * Whether or not to show the script portion of the source code + * @param showScriptClass + * Whether or not to show the Script class from the source code + * @returns the source code from the AST state + */ String compileToScript(String script, int compilePhase, ClassLoader classLoader = null, boolean showScriptFreeForm = true, boolean showScriptClass = true) { def writer = new StringWriter() @@ -113,8 +111,6 @@ and [compilephase] is a valid Integer based org.codehaus.groovy.control.CompileP /** * An adapter from ASTNode tree to source code. - * - * @author Hamlet D'Arcy */ class AstNodeToScriptVisitor extends PrimaryClassNodeOperation implements GroovyCodeVisitor, GroovyClassVisitor { @@ -267,7 +263,8 @@ class AstNodeToScriptVisitor extends PrimaryClassNodeOperation implements Groovy } visitModifiers(node.modifiers) - print "class $node.name" + if (node.isInterface()) print node.name + else print "class $node.name" visitGenerics node?.genericsTypes boolean first = true node.unresolvedInterfaces?.each { @@ -402,40 +399,10 @@ class AstNodeToScriptVisitor extends PrimaryClassNodeOperation implements Groovy printDoubleBreak() } - private def visitModifiers(int modifiers) { - if (Modifier.isAbstract(modifiers)) { - print 'abstract ' - } - if (Modifier.isFinal(modifiers)) { - print 'final ' - } - if (Modifier.isInterface(modifiers)) { - print 'interface ' - } - if (Modifier.isNative(modifiers)) { - print 'native ' - } - if (Modifier.isPrivate(modifiers)) { - print 'private ' - } - if (Modifier.isProtected(modifiers)) { - print 'protected ' - } - if (Modifier.isPublic(modifiers)) { - print 'public ' - } - if (Modifier.isStatic(modifiers)) { - print 'static ' - } - if (Modifier.isSynchronized(modifiers)) { - print 'synchronized ' - } - if (Modifier.isTransient(modifiers)) { - print 'transient ' - } - if (Modifier.isVolatile(modifiers)) { - print 'volatile ' - } + private void visitModifiers(int modifiers) { + String mods = Modifier.toString(modifiers) + mods = mods ? mods + ' ' : mods + print mods } @Override @@ -458,7 +425,7 @@ class AstNodeToScriptVisitor extends PrimaryClassNodeOperation implements Groovy // GROOVY-5150: final constants may be initialized directly print ' = ' if (ClassHelper.STRING_TYPE == type) { - print "'"+node.initialValueExpression.text.replaceAll("'", "\\\\'")+"'" + print "'" + node.initialValueExpression.text.replaceAll("'", "\\\\'") + "'" } else if (ClassHelper.char_TYPE == type) { print "'${node.initialValueExpression.text}'" } else { @@ -635,7 +602,7 @@ class AstNodeToScriptVisitor extends PrimaryClassNodeOperation implements Groovy if (expression?.arguments instanceof VariableExpression || expression?.arguments instanceof MethodCallExpression) { print '(' expression?.arguments?.visit this - print ')' + print ')' } else { expression?.arguments?.visit this } @@ -825,7 +792,6 @@ class AstNodeToScriptVisitor extends PrimaryClassNodeOperation implements Groovy /** * Prints out the type, safely handling arrays. * @param classNode - * classnode */ void visitType(ClassNode classNode) { def name = classNode.name @@ -866,7 +832,6 @@ class AstNodeToScriptVisitor extends PrimaryClassNodeOperation implements Groovy } - @Override void visitMapExpression(MapExpression expression) { print '[' http://git-wip-us.apache.org/repos/asf/groovy/blob/4bca3fea/subprojects/groovy-console/src/test/groovy/groovy/inspect/swingui/AstNodeToScriptAdapterTest.groovy ---------------------------------------------------------------------- diff --git a/subprojects/groovy-console/src/test/groovy/groovy/inspect/swingui/AstNodeToScriptAdapterTest.groovy b/subprojects/groovy-console/src/test/groovy/groovy/inspect/swingui/AstNodeToScriptAdapterTest.groovy index dbb4967..48c0640 100644 --- a/subprojects/groovy-console/src/test/groovy/groovy/inspect/swingui/AstNodeToScriptAdapterTest.groovy +++ b/subprojects/groovy-console/src/test/groovy/groovy/inspect/swingui/AstNodeToScriptAdapterTest.groovy @@ -19,10 +19,15 @@ package groovy.inspect.swingui import org.codehaus.groovy.ast.VariableScope +import org.codehaus.groovy.ast.expr.BooleanExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.DoWhileStatement import org.codehaus.groovy.control.CompilePhase -import org.codehaus.groovy.ast.expr.* + +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt /** * Unit test for ScriptToTreeNodeAdapter. @@ -30,8 +35,6 @@ import org.codehaus.groovy.ast.expr.* * The assertions in this test case often assert against the toString() representation of * an object. Normally, this is bad form. However, the class under test is meant to display * toString() forms in a user interface. So in this case it is appropriate. - * - * @author Hamlet D'Arcy */ class AstNodeToScriptAdapterTest extends GroovyTestCase { @@ -93,7 +96,7 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { assert result.contains('protected void method4()') assert result.contains('public java.lang.Object method5(java.lang.Object parm1)') assert result.contains('public static java.lang.Object method6(java.lang.String parm1)') - assert result.contains('native public java.lang.Object method7(java.lang.Object parm1, final java.lang.Object parm2)') + assert result.contains('public native java.lang.Object method7(java.lang.Object parm1, final java.lang.Object parm2)') assert result.contains('public synchronized java.lang.Object method8(java.lang.String parm1, final java.lang.String parm2)') assert result.contains("public java.lang.Object method9(java.lang.String parm1 = this.getValue(), java.lang.String parm2 = 'somevalue')") assert result.contains('public java.lang.Integer[] method10(java.lang.String[] parm1, java.lang.Object[] parm2)') @@ -200,7 +203,7 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { String result = compileToScript(script, CompilePhase.CLASS_GENERATION) assert result.contains('java.lang.String[] x = (([]) as java.lang.String[])') - assert result.contains('final private java.lang.String[] arr') + assert result.contains('private final java.lang.String[] arr') assert result.contains('arr = new java.lang.String[0]') } @@ -214,7 +217,7 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { String result = compileToScript(script, CompilePhase.CLASS_GENERATION) assert result.contains('java.lang.String[][] x = (([]) as java.lang.String[][])') assert result.contains('java.lang.String[][][] y = (([]) as java.lang.String[][][])') - assert result.contains('final private java.lang.String[][] arr') + assert result.contains('private final java.lang.String[][] arr') assert result.contains('arr = new java.lang.String[this.xSize(), 3]') } @@ -316,7 +319,7 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { } }''' String result = compileToScript(script, CompilePhase.CLASS_GENERATION) - assert result.contains('final private static transient java.util.logging.Logger log') + assert result.contains('private static final transient java.util.logging.Logger log') assert result.contains("log = java.util.logging.Logger.getLogger('Event')") assert result.contains('return log.isLoggable(java.util.logging.Level.FINE) ? log.fine(this.someMethod()) : null') } @@ -442,7 +445,7 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { boolean p2() default false; } ''' - + String result = compileToScript(script) assert result.contains('@java.lang.SuppressWarnings') @@ -566,9 +569,9 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { }''' String result = compileToScript(script, CompilePhase.CLASS_GENERATION) - assert result.contains('final private java.lang.String title') - assert result.contains('final private java.util.Date when') - assert result.contains('final private java.awt.Color color') + assert result.contains('private final java.lang.String title') + assert result.contains('private final java.util.Date when') + assert result.contains('private final java.awt.Color color') // assert hashCode assert result.contains('public int hashCode()') @@ -582,15 +585,17 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { } void testAnonymousInnerClass() { - String script = '''new Object() { - public String toString() { 'foo' } - }''' + String script = ''' + new Object() { + public String toString() { 'foo' } + } + ''' String result = compileToScript(script, CompilePhase.CANONICALIZATION) assert result =~ /new script[0-9].*\$1/ assert result =~ /public class script[0-9].*\$1/ - assert result =~ /public java\.lang\.String toString()/ + assert result =~ /public java\.lang\.String toString\(\)/ } void testLazyAnnotation() { @@ -651,14 +656,16 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { } void testSuperAndThisCalls() { - String script = '''class MyClass { + String script = ''' + class MyClass { MyClass() { this('foo') } MyClass(foo) { super(foo) } - }''' + } + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("this ('foo')") @@ -710,9 +717,10 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { void testDoWhileLoop() { def doWhile = new DoWhileStatement( - new BooleanExpression(new ConstantExpression(true)), + new BooleanExpression(constX(true)), new BlockStatement( - [new MethodCallExpression(new VariableExpression('this'), 'println', new ArgumentListExpression(new ConstantExpression('value')))], new VariableScope() + [stmt(callThisX('println', args(constX('value'))))], + new VariableScope() )) StringWriter writer = new StringWriter() @@ -731,18 +739,20 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { } void testMethodPointer() { - String script = '''class Event { - static def staticMethod(it) { it * it } - def instanceMethod(it) { it / it } - } + String script = ''' + class Event { + static def staticMethod(it) { it * it } + def instanceMethod(it) { it / it } + } - def m1 = Event.&'staticMethod' - assert 25 == m1(5) - def m2 = new Event().&'instanceMethod' - assert 1 == m2(5) - def e = new Event() - def m3 = e.&'instanceMethod' - assert 1 == m3(6) ''' + def m1 = Event.&'staticMethod' + assert 25 == m1(5) + def m2 = new Event().&'instanceMethod' + assert 1 == m2(5) + def e = new Event() + def m3 = e.&'instanceMethod' + assert 1 == m3(6) + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("java.lang.Object m1 = Event.&'staticMethod'") @@ -755,8 +765,10 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { } void testAssertRegexExpression() { - String script = ''' assert "abc.def" =~ /[a-z]b[a-z]\\.def/ - assert "cheesecheese" =~ "cheese" ''' + String script = ''' + assert "abc.def" =~ /[a-z]b[a-z]\\.def/ + assert "cheesecheese" =~ "cheese" + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("assert 'abc.def' =~ '[a-z]b[a-z]\\.def' : null") @@ -764,8 +776,10 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { } void testArrayExpression() { - String script = '''def x = [4, 5, 6] as String[] - [1, 2, 3] << new Integer[x.length]''' + String script = ''' + def x = [4, 5, 6] as String[] + [1, 2, 3] << new Integer[x.length] + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains('java.lang.Object x = (([4, 5, 6]) as java.lang.String[])') assert result.contains('[1, 2, 3] << new java.lang.Integer[ x .length]') @@ -773,9 +787,10 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { void testSpreadDot() { String script = ''' - def x = [ ['a':11, 'b':12], ['a':21, 'b':22] ] - assert x.a == [11, 21] //GPath notation - assert x*.a == [11, 21] //spread dot notation ''' + def x = [ ['a':11, 'b':12], ['a':21, 'b':22] ] + assert x.a == [11, 21] //GPath notation + assert x*.a == [11, 21] //spread dot notation + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("java.lang.Object x = [['a': 11, 'b': 12], ['a': 21, 'b': 22]]") assert result.contains('assert x .a == [11, 21] : null') @@ -784,9 +799,10 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { void testSpreadNotationNullHandling() { String script = ''' - def x = [ ['a':11, 'b':12], ['a':21, 'b':22], null ] - assert x*.a == [11, 21, null] //caters for null values - assert x*.a == x.collect{ it?.a } //equivalent notation ''' + def x = [ ['a':11, 'b':12], ['a':21, 'b':22], null ] + assert x*.a == [11, 21, null] //caters for null values + assert x*.a == x.collect{ it?.a } //equivalent notation + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("java.lang.Object x = [['a': 11, 'b': 12], ['a': 21, 'b': 22], null]") @@ -798,10 +814,10 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { void testSpreadNotationAdvanced() { String script = ''' - class MyClass{ def getA(){ 'abc' } } - def x = [ ['a':21, 'b':22], null, new MyClass() ] - assert x*.a == [21, null, 'abc'] //properties treated like map subscripting - ''' + class MyClass{ def getA(){ 'abc' } } + def x = [ ['a':21, 'b':22], null, new MyClass() ] + assert x*.a == [21, null, 'abc'] //properties treated like map subscripting + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("java.lang.Object x = [['a': 21, 'b': 22], null, new MyClass()]") assert result.contains("assert x *.a == [21, null, 'abc'] : null") @@ -809,11 +825,12 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { void testSpreadNotationForMethodsOnLists() { String script = ''' - class MyClass{ def getA(){ 'abc' } } - def c1= new MyClass(), c2= new MyClass() - assert [c1, c2]*.getA() == [c1.getA(), c2.getA()] - //spread dot also works for method calls - assert [c1, c2]*.getA() == ['abc', 'abc'] ''' + class MyClass{ def getA(){ 'abc' } } + def c1= new MyClass(), c2= new MyClass() + assert [c1, c2]*.getA() == [c1.getA(), c2.getA()] + //spread dot also works for method calls + assert [c1, c2]*.getA() == ['abc', 'abc'] + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains('java.lang.Object c1 = new MyClass()') assert result.contains('java.lang.Object c2 = new MyClass()') @@ -829,8 +846,9 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { void testSpreadNotationInMapDefinition() { String script = ''' - assert ['z':900, *:['a':100, 'b':200], 'a':300] == ['a':300, 'b':200, 'z':900] - assert [ *:[3:3, *:[5:5] ], 7:7] == [3:3, 5:5, 7:7] ''' + assert ['z':900, *:['a':100, 'b':200], 'a':300] == ['a':300, 'b':200, 'z':900] + assert [ *:[3:3, *:[5:5] ], 7:7] == [3:3, 5:5, 7:7] + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("assert ['z': 900, *: ['a': 100, 'b': 200], 'a': 300] == ['a': 300, 'b': 200, 'z': 900] : null") assert result.contains('assert [*: [3: 3, *: [5: 5]], 7: 7] == [3: 3, 5: 5, 7: 7] : null') @@ -838,13 +856,14 @@ class AstNodeToScriptAdapterTest extends GroovyTestCase { void testSpreadNotationInClosure() { String script = ''' - def f(){ [ 1:'u', 2:'v', 3:'w' ] } - assert [*:f(), 10:'zz'] == [1:'u', 10:'zz', 2:'v', 3:'w'] - def f(m){ m.c } - assert f(*:['a':10, 'b':20, 'c':30], 'e':50) == 30 + def f(){ [ 1:'u', 2:'v', 3:'w' ] } + assert [*:f(), 10:'zz'] == [1:'u', 10:'zz', 2:'v', 3:'w'] + def f(m){ m.c } + assert f(*:['a':10, 'b':20, 'c':30], 'e':50) == 30 - def f(m, i, j, k){ [m, i, j, k] } - assert f('e':100, *[4, 5], *:['a':10, 'b':20, 'c':30], 6) == [ ["e":100, "b":20, "c":30, "a":10], 4, 5, 6 ]''' + def f(m, i, j, k){ [m, i, j, k] } + assert f('e':100, *[4, 5], *:['a':10, 'b':20, 'c':30], 6) == [ ["e":100, "b":20, "c":30, "a":10], 4, 5, 6 ] + ''' String result = compileToScript(script, CompilePhase.SEMANTIC_ANALYSIS) assert result.contains("assert [*: this.f(), 10: 'zz'] == [1: 'u', 10: 'zz', 2: 'v', 3: 'w'] : null") assert result.contains("assert this.f([*: ['a': 10, 'b': 20, 'c': 30], 'e': 50]) == 30 : null")