You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/11/01 09:04:23 UTC
[1/2] groovy git commit: GROOVY-8357:
EncodingGroovyMethods.decodeBase64() throws "bad character in base64 value"
when meets \t \r (closes #623)
Repository: groovy
Updated Branches:
refs/heads/master b23ef5394 -> 771240d07
GROOVY-8357: EncodingGroovyMethods.decodeBase64() throws "bad character in base64 value" when meets \t \r (closes #623)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/9030fbf0
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/9030fbf0
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/9030fbf0
Branch: refs/heads/master
Commit: 9030fbf0b1faf4e72e79100295a8c636665ea2e4
Parents: b23ef53
Author: paulk <pa...@asert.com.au>
Authored: Mon Oct 30 12:37:05 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Wed Nov 1 17:43:24 2017 +1000
----------------------------------------------------------------------
.../runtime/EncodingGroovyMethodsSupport.java | 58 ++++++++++----------
src/test/groovy/Base64Test.groovy | 3 +
2 files changed, 32 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/9030fbf0/src/main/org/codehaus/groovy/runtime/EncodingGroovyMethodsSupport.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/EncodingGroovyMethodsSupport.java b/src/main/org/codehaus/groovy/runtime/EncodingGroovyMethodsSupport.java
index ef134bd..24929a8 100644
--- a/src/main/org/codehaus/groovy/runtime/EncodingGroovyMethodsSupport.java
+++ b/src/main/org/codehaus/groovy/runtime/EncodingGroovyMethodsSupport.java
@@ -24,67 +24,67 @@ package org.codehaus.groovy.runtime;
public class EncodingGroovyMethodsSupport {
static final byte[] TRANSLATE_TABLE = (
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
- // \t \n \r
- + "\u0042\u0042\u0041\u0041\u0042\u0042\u0041\u0042"
+ // \t \n \r
+ + "\u0042\u0041\u0041\u0042\u0042\u0041\u0042\u0042"
//
+ "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
//
+ "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
- // sp ! " # $ % & '
+ // sp ! " # $ % & '
+ "\u0041\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
- // ( ) * + , - . /
+ // ( ) * + , - . /
+ "\u0042\u0042\u0042\u003E\u0042\u0042\u0042\u003F"
- // 0 1 2 3 4 5 6 7
+ // 0 1 2 3 4 5 6 7
+ "\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B"
- // 8 9 : ; < = > ?
+ // 8 9 : ; < = > ?
+ "\u003C\u003D\u0042\u0042\u0042\u0040\u0042\u0042"
- // @ A B C D E F G
+ // @ A B C D E F G
+ "\u0042\u0000\u0001\u0002\u0003\u0004\u0005\u0006"
- // H I J K L M N O
+ // H I J K L M N O
+ "\u0007\u0008\t\n\u000B\u000C\r\u000E"
- // P Q R S T U V W
+ // P Q R S T U V W
+ "\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016"
- // X Y Z [ \ ] ^ _
+ // X Y Z [ \ ] ^ _
+ "\u0017\u0018\u0019\u0042\u0042\u0042\u0042\u0042"
- // ' a b c d e f g
+ // ' a b c d e f g
+ "\u0042\u001A\u001B\u001C\u001D\u001E\u001F\u0020"
- // h i j k l m n o p
+ // h i j k l m n o
+ "\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028"
- // p q r s t u v w
+ // p q r s t u v w
+ "\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030"
- // x y z
+ // x y z
+ "\u0031\u0032\u0033").getBytes();
static final byte[] TRANSLATE_TABLE_URLSAFE = (
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
- // \t \n \r
- + "\u0042\u0042\u0041\u0041\u0042\u0042\u0041\u0042"
+ // \t \n \r
+ + "\u0042\u0041\u0041\u0042\u0042\u0041\u0042\u0042"
//
+ "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
//
+ "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
- // sp ! " # $ % & '
+ // sp ! " # $ % & '
+ "\u0041\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
- // ( ) * + , - . /
+ // ( ) * + , - . /
+ "\u0042\u0042\u0042\u0042\u0042\u003E\u0042\u0042"
- // 0 1 2 3 4 5 6 7
+ // 0 1 2 3 4 5 6 7
+ "\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B"
- // 8 9 : ; < = > ?
+ // 8 9 : ; < = > ?
+ "\u003C\u003D\u0042\u0042\u0042\u0040\u0042\u0042"
- // @ A B C D E F G
+ // @ A B C D E F G
+ "\u0042\u0000\u0001\u0002\u0003\u0004\u0005\u0006"
- // H I J K L M N O
+ // H I J K L M N O
+ "\u0007\u0008\t\n\u000B\u000C\r\u000E"
- // P Q R S T U V W
+ // P Q R S T U V W
+ "\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016"
- // X Y Z [ \ ] ^ _
+ // X Y Z [ \ ] ^ _
+ "\u0017\u0018\u0019\u0042\u0042\u0042\u0042\u003F"
- // ' a b c d e f g
+ // ' a b c d e f g
+ "\u0042\u001A\u001B\u001C\u001D\u001E\u001F\u0020"
- // h i j k l m n o p
+ // h i j k l m n o
+ "\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028"
- // p q r s t u v w
+ // p q r s t u v w
+ "\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030"
- // x y z
+ // x y z
+ "\u0031\u0032\u0033").getBytes();
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/9030fbf0/src/test/groovy/Base64Test.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/Base64Test.groovy b/src/test/groovy/Base64Test.groovy
index 2f23bba..0904f86 100644
--- a/src/test/groovy/Base64Test.groovy
+++ b/src/test/groovy/Base64Test.groovy
@@ -61,6 +61,9 @@ class Base64Test extends GroovyTestCase {
assert line0.size() == 76
assert line0 == 'pzEyMzQ1Njc4OTAtPbEhQKMkJV4mKigpXytxd2VydHl1aW9wW11RV0VSVFlVSU9Qe31hc2RmZ2hq'
assert line1 == 'a2w7J1xBU0RGR0hKS0w6InxgenhjdmJubSwuL35aWENWQk5NPD4/A//wDw=='
+ // check we allow \n \r \t and space to be ignored when decoding for round-tripping purposes
+ assert encodedBytes.decodeBase64() == testBytes
+ assert (encodedBytes + '\t ').decodeBase64() == testBytes
}
void testNonChunked() {
[2/2] groovy git commit: GROOVY-8112: NPE in Groovy compiler when
referencing @Field in aic (closes #622)
Posted by pa...@apache.org.
GROOVY-8112: NPE in Groovy compiler when referencing @Field in aic (closes #622)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/771240d0
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/771240d0
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/771240d0
Branch: refs/heads/master
Commit: 771240d073fa7fc7e16727e5aa1fdbd5df20d490
Parents: 9030fbf
Author: paulk <pa...@asert.com.au>
Authored: Mon Oct 30 08:47:28 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Wed Nov 1 19:02:39 2017 +1000
----------------------------------------------------------------------
.../transform/FieldASTTransformation.java | 104 +++++++++++++++----
.../groovy/transform/FieldTransformTest.groovy | 39 ++++++-
2 files changed, 122 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/771240d0/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java b/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
index 52b4406..8e6b58e 100644
--- a/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
@@ -27,15 +27,19 @@ import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.VariableScope;
-import org.codehaus.groovy.ast.expr.BinaryExpression;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
import org.codehaus.groovy.ast.expr.DeclarationExpression;
import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.classgen.VariableScopeVisitor;
@@ -44,6 +48,7 @@ import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.objectweb.asm.Opcodes;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
@@ -59,9 +64,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
/**
* Handles transformation for the @Field annotation.
- *
- * @author Paul King
- * @author Cedric Champeau
*/
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class FieldASTTransformation extends ClassCodeExpressionTransformer implements ASTTransformation, Opcodes {
@@ -77,6 +79,7 @@ public class FieldASTTransformation extends ClassCodeExpressionTransformer imple
private String variableName;
private FieldNode fieldNode;
private ClosureExpression currentClosure;
+ private ConstructorCallExpression currentAIC;
public void visit(ASTNode[] nodes, SourceUnit source) {
sourceUnit = source;
@@ -166,23 +169,76 @@ public class FieldASTTransformation extends ClassCodeExpressionTransformer imple
} else if (insideScriptBody && expr instanceof VariableExpression && currentClosure != null) {
VariableExpression ve = (VariableExpression) expr;
if (ve.getName().equals(variableName)) {
- // we may only check the variable name because the Groovy compiler
- // already fails if a variable with the same name already exists in the scope.
- // this means that a closure cannot shadow a class variable
- ve.setAccessedVariable(fieldNode);
- final VariableScope variableScope = currentClosure.getVariableScope();
- final Iterator<Variable> iterator = variableScope.getReferencedLocalVariablesIterator();
- while (iterator.hasNext()) {
- Variable next = iterator.next();
- if (next.getName().equals(variableName)) iterator.remove();
- }
- variableScope.putReferencedClassVariable(fieldNode);
+ adjustToClassVar(ve);
return ve;
}
+ } else if (currentAIC != null && expr instanceof ArgumentListExpression) {
+ // if a match is found, the compiler will have already set up aic constructor to hav
+ // an argument which isn't needed since we'll be accessing the field; we must undo it
+ Expression skip = null;
+ List<Expression> origArgList = ((ArgumentListExpression) expr).getExpressions();
+ for (int i = 0; i < origArgList.size(); i++) {
+ Expression arg = origArgList.get(i);
+ if (matchesCandidate(arg)) {
+ skip = arg;
+ adjustConstructorAndFields(i, currentAIC.getType());
+ break;
+ }
+ }
+ if (skip != null) {
+ return adjustedArgList(skip, origArgList);
+ }
}
return expr.transformExpression(this);
}
+ private boolean matchesCandidate(Expression arg) {
+ return arg instanceof VariableExpression && ((VariableExpression) arg).getAccessedVariable() == candidate.getVariableExpression().getAccessedVariable();
+ }
+
+ private Expression adjustedArgList(Expression skip, List<Expression> origArgs) {
+ List<Expression> newArgs = new ArrayList<Expression>(origArgs.size() - 1);
+ for (Expression origArg : origArgs) {
+ if (skip != origArg) {
+ newArgs.add(origArg);
+ }
+ }
+ return new ArgumentListExpression(newArgs);
+ }
+
+ private void adjustConstructorAndFields(int skipIndex, ClassNode type) {
+ List<ConstructorNode> constructors = type.getDeclaredConstructors();
+ if (constructors.size() == 1) {
+ ConstructorNode constructor = constructors.get(0);
+ Parameter[] params = constructor.getParameters();
+ Parameter[] newParams = new Parameter[params.length - 1];
+ int to = 0;
+ for (int from = 0; from < params.length; from++) {
+ if (from != skipIndex) {
+ newParams[to++] = params[from];
+ }
+ }
+ type.removeConstructor(constructor);
+ // code doesn't mention the removed param at this point, okay to leave as is
+ type.addConstructor(constructor.getModifiers(), newParams, constructor.getExceptions(), constructor.getCode());
+ type.removeField(variableName);
+ }
+ }
+
+ private void adjustToClassVar(VariableExpression expr) {
+ // we only need to check the variable name because the Groovy compiler
+ // already fails if a variable with the same name already exists in the scope.
+ // this means that a closure cannot shadow a class variable
+ expr.setAccessedVariable(fieldNode);
+ final VariableScope variableScope = currentClosure.getVariableScope();
+ final Iterator<Variable> iterator = variableScope.getReferencedLocalVariablesIterator();
+ while (iterator.hasNext()) {
+ Variable next = iterator.next();
+ if (next.getName().equals(variableName)) iterator.remove();
+ }
+ variableScope.putReferencedClassVariable(fieldNode);
+ }
+
@Override
public void visitClosureExpression(final ClosureExpression expression) {
ClosureExpression old = currentClosure;
@@ -192,6 +248,20 @@ public class FieldASTTransformation extends ClassCodeExpressionTransformer imple
}
@Override
+ public void visitConstructorCallExpression(final ConstructorCallExpression cce) {
+ if (!insideScriptBody || !cce.isUsingAnonymousInnerClass()) return;
+ ConstructorCallExpression old = currentAIC;
+ currentAIC = cce;
+ Expression newArgs = transform(cce.getArguments());
+ if (cce.getArguments() instanceof TupleExpression && newArgs instanceof TupleExpression) {
+ List<Expression> argList = ((TupleExpression) cce.getArguments()).getExpressions();
+ argList.clear();
+ argList.addAll(((TupleExpression) newArgs).getExpressions());
+ }
+ currentAIC = old;
+ }
+
+ @Override
public void visitMethod(MethodNode node) {
Boolean oldInsideScriptBody = insideScriptBody;
if (node.isScriptBody()) insideScriptBody = true;
@@ -202,9 +272,7 @@ public class FieldASTTransformation extends ClassCodeExpressionTransformer imple
@Override
public void visitExpressionStatement(ExpressionStatement es) {
Expression exp = es.getExpression();
- if (exp instanceof BinaryExpression) {
- exp.visit(this);
- }
+ exp.visit(this);
super.visitExpressionStatement(es);
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/771240d0/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy b/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy
index 2821f6e..6575720 100644
--- a/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy
@@ -21,8 +21,7 @@ package org.codehaus.groovy.transform
import gls.CompilableTestSupport
/**
- * @author Paul King
- * @author C�dric Champeau
+ * Tests for the {@code @Field} transformation
*/
class FieldTransformTest extends CompilableTestSupport {
@@ -226,4 +225,38 @@ class FieldTransformTest extends CompilableTestSupport {
assert foo + bar + baz == 'foobarbaz'
'''
}
-}
\ No newline at end of file
+
+ void testAnonymousInnerClassReferencesToField() {
+ // GROOVY-8112
+ assertScript '''
+ @groovy.transform.Field
+ StringBuilder logger = new StringBuilder()
+ logger.append('a')
+ ['b'].each {
+ logger.append(it)
+ new Object() {
+ String toString() {
+ logger.append('c')
+ ['d'].each { logger.append(it) }
+ }
+ }.toString()
+ }
+ Closure c = { logger.append('e') }
+ c()
+ // control: worked previously, make sure we didn't break
+ def method() {
+ logger.append('f')
+ ['g'].each {
+ logger.append(it)
+ new Object() {
+ String toString() {
+ logger.append('h')
+ }
+ }.toString()
+ }
+ }
+ method()
+ assert logger.toString() == 'abcdefgh'
+ '''
+ }
+}