GROOVY-8023: changing O(n^2) time complexity of transformMethodCall in SuperCallTraitTransformer to O(n)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/d3dd6949 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/d3dd6949 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/d3dd6949 Branch: refs/heads/parrot Commit: d3dd694969e85050b2b127280ad5ca7dcdfd2180 Parents: e96a961 Author: Jochen Theodorou <blackd...@gmx.org> Authored: Thu Jan 26 21:01:35 2017 +0100 Committer: Jochen Theodorou <blackd...@gmx.org> Committed: Thu Jan 26 21:01:35 2017 +0100 ---------------------------------------------------------------------- .../trait/SuperCallTraitTransformer.java | 40 ++++++++++++++------ .../codehaus/groovy/transform/trait/Traits.java | 2 +- 2 files changed, 29 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/d3dd6949/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java index e403a2c..6ebc5f2 100644 --- a/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java +++ b/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java @@ -19,6 +19,7 @@ package org.codehaus.groovy.transform.trait; import groovy.lang.MetaProperty; +import java.util.List; import org.codehaus.groovy.ast.ClassCodeExpressionTransformer; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.MethodNode; @@ -34,8 +35,6 @@ import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.syntax.Types; -import java.util.List; - /** * This transformer is used to transform calls to <code>SomeTrait.super.foo()</code> into the appropriate trait call. * @@ -56,9 +55,6 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer { @Override public Expression transform(final Expression exp) { - if (exp instanceof PropertyExpression) { - return transformPropertyExpression((PropertyExpression) exp); - } if (exp instanceof MethodCallExpression) { return transformMethodCallExpression((MethodCallExpression)exp); } @@ -74,12 +70,17 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer { BinaryExpression bin = (BinaryExpression) trn; Expression leftExpression = bin.getLeftExpression(); if (bin.getOperation().getType() == Types.EQUAL && leftExpression instanceof PropertyExpression) { - ClassNode traitReceiver = ((PropertyExpression) leftExpression).getObjectExpression().getNodeMetaData(SuperCallTraitTransformer.class); + ClassNode traitReceiver = null; + PropertyExpression leftPropertyExpression = (PropertyExpression) leftExpression; + if (isTraitSuperPropertyExpression(leftPropertyExpression.getObjectExpression())) { + PropertyExpression pexp = (PropertyExpression) leftPropertyExpression.getObjectExpression(); + traitReceiver = pexp.getObjectExpression().getType(); + } if (traitReceiver!=null) { // A.super.foo = ... TraitHelpersTuple helpers = Traits.findHelpers(traitReceiver); ClassNode helper = helpers.getHelper(); - String setterName = MetaProperty.getSetterName(((PropertyExpression) leftExpression).getPropertyAsString()); + String setterName = MetaProperty.getSetterName(leftPropertyExpression.getPropertyAsString()); List<MethodNode> methods = helper.getMethods(setterName); for (MethodNode method : methods) { Parameter[] parameters = method.getParameters(); @@ -106,9 +107,10 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer { } private Expression transformMethodCallExpression(final MethodCallExpression exp) { - Expression objectExpression = transform(exp.getObjectExpression()); - ClassNode traitReceiver = objectExpression.getNodeMetaData(SuperCallTraitTransformer.class); - if (traitReceiver!=null) { + if (isTraitSuperPropertyExpression(exp.getObjectExpression())) { + Expression objectExpression = exp.getObjectExpression(); + ClassNode traitReceiver = ((PropertyExpression) objectExpression).getObjectExpression().getType(); + TraitHelpersTuple helpers = Traits.findHelpers(traitReceiver); // (SomeTrait.super).foo() --> SomeTrait$Helper.foo(this) ClassExpression receiver = new ClassExpression( @@ -123,11 +125,11 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer { newArgs.addExpression(transform(expression)); } } else { - newArgs.addExpression(arguments); + newArgs.addExpression(transform(arguments)); } MethodCallExpression result = new MethodCallExpression( receiver, - exp.getMethod(), + transform(exp.getMethod()), newArgs ); result.setImplicitThis(false); @@ -150,4 +152,18 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer { } return super.transform(expression); } + + private boolean isTraitSuperPropertyExpression(Expression exp) { + if (exp instanceof PropertyExpression) { + PropertyExpression pexp = (PropertyExpression) exp; + Expression objectExpression = pexp.getObjectExpression(); + if (objectExpression instanceof ClassExpression) { + ClassNode type = objectExpression.getType(); + if (Traits.isTrait(type) && "super".equals(pexp.getPropertyAsString())) { + return true; + } + } + } + return false; + } } http://git-wip-us.apache.org/repos/asf/groovy/blob/d3dd6949/src/main/org/codehaus/groovy/transform/trait/Traits.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/transform/trait/Traits.java b/src/main/org/codehaus/groovy/transform/trait/Traits.java index 4a0ac91..b1c9537 100644 --- a/src/main/org/codehaus/groovy/transform/trait/Traits.java +++ b/src/main/org/codehaus/groovy/transform/trait/Traits.java @@ -136,7 +136,7 @@ public abstract class Traits { try { final ClassLoader classLoader = trait.getTypeClass().getClassLoader(); String helperClassName = Traits.helperClassName(trait); - helperClassNode = ClassHelper.make(classLoader.loadClass(helperClassName)); + helperClassNode = ClassHelper.make(Class.forName(helperClassName, false, classLoader)); try { fieldHelperClassNode = ClassHelper.make(classLoader.loadClass(Traits.fieldHelperClassName(trait))); } catch (ClassNotFoundException e) {