http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java new file mode 100644 index 0000000..d1a3596 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java @@ -0,0 +1,140 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.AnnotationNode; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; +import org.codehaus.groovy.ast.NodeMetaDataHandler; + +import java.util.List; +import java.util.Map; + +/** + * This class is a place holder for an empty expression. + * Empty expression are used in closures lists like (;). During + * class Generation this expression should be either ignored or + * replace with a null value. + * + * @author Jochen Theodorou + * @see org.codehaus.groovy.ast.stmt.EmptyStatement + */ +public class EmptyExpression extends Expression { + public static final EmptyExpression INSTANCE = new EmptyExpression(); + + /** + * use EmptyExpression.INSTANCE instead + */ + @Deprecated + public EmptyExpression() {} + + public Expression transformExpression(ExpressionTransformer transformer) { + return this; + } + + public void visit(GroovyCodeVisitor visitor) { + return; + } + + + @Override + public void setType(ClassNode t) { + throw createUnsupportedOperationException(); + } + + @Override + public void addAnnotation(AnnotationNode value) { + throw createUnsupportedOperationException(); + } + + @Override + public void addAnnotations(List<AnnotationNode> annotations) { + throw createUnsupportedOperationException(); + } + + @Override + public void setSynthetic(boolean synthetic) { + throw createUnsupportedOperationException(); + } + + @Override + public void setDeclaringClass(ClassNode declaringClass) { + throw createUnsupportedOperationException(); + } + + @Override + public void setHasNoRealSourcePosition(boolean value) { + throw createUnsupportedOperationException(); + } + + @Override + public void setLineNumber(int lineNumber) { + throw createUnsupportedOperationException(); + } + + @Override + public void setColumnNumber(int columnNumber) { + throw createUnsupportedOperationException(); + } + + @Override + public void setLastLineNumber(int lastLineNumber) { + throw createUnsupportedOperationException(); + } + + @Override + public void setLastColumnNumber(int lastColumnNumber) { + throw createUnsupportedOperationException(); + } + + @Override + public void setSourcePosition(ASTNode node) { + throw createUnsupportedOperationException(); + } + + @Override + public void copyNodeMetaData(NodeMetaDataHandler other) { + throw createUnsupportedOperationException(); + } + + @Override + public void setNodeMetaData(Object key, Object value) { + throw createUnsupportedOperationException(); + } + + @Override + public Object putNodeMetaData(Object key, Object value) { + throw createUnsupportedOperationException(); + } + + @Override + public void removeNodeMetaData(Object key) { + throw createUnsupportedOperationException(); + } + + @Override + public void setMetaDataMap(Map<?, ?> metaDataMap) { + throw createUnsupportedOperationException(); + } + + private UnsupportedOperationException createUnsupportedOperationException() { + return new UnsupportedOperationException("EmptyExpression.INSTANCE is immutable"); + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/Expression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/Expression.java b/src/main/java/org/codehaus/groovy/ast/expr/Expression.java new file mode 100644 index 0000000..f9991d2 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/Expression.java @@ -0,0 +1,81 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.GroovyBugError; +import org.codehaus.groovy.ast.AnnotatedNode; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a base class for expressions which evaluate as an object + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public abstract class Expression extends AnnotatedNode { + public static final Expression[] EMPTY_ARRAY = new Expression[0]; + private ClassNode type=ClassHelper.DYNAMIC_TYPE; + + /** + * Return a copy of the expression calling the transformer on any nested expressions + * @param transformer + */ + public abstract Expression transformExpression(ExpressionTransformer transformer); + + /** + * Transforms the list of expressions + * @return a new list of transformed expressions + */ + protected List<Expression> transformExpressions(List<? extends Expression> expressions, ExpressionTransformer transformer) { + List<Expression> list = new ArrayList<Expression>(expressions.size()); + for (Expression expr : expressions ) { + list.add(transformer.transform(expr)); + } + return list; + } + + /** + * Transforms the list of expressions, and checks that all transformed expressions have the given type. + * + * @return a new list of transformed expressions + */ + protected <T extends Expression> List<T> transformExpressions(List<? extends Expression> expressions, + ExpressionTransformer transformer, Class<T> transformedType) { + List<T> list = new ArrayList<T>(expressions.size()); + for (Expression expr : expressions) { + Expression transformed = transformer.transform(expr); + if (!transformedType.isInstance(transformed)) + throw new GroovyBugError(String.format("Transformed expression should have type %s but has type %s", + transformedType, transformed.getClass())); + list.add(transformedType.cast(transformed)); + } + return list; + } + + public ClassNode getType() { + return type; + } + + public void setType(ClassNode t) { + type=t; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/ExpressionTransformer.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ExpressionTransformer.java b/src/main/java/org/codehaus/groovy/ast/expr/ExpressionTransformer.java new file mode 100644 index 0000000..459ed43 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/ExpressionTransformer.java @@ -0,0 +1,33 @@ +/* + * 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.ast.expr; + + +/** + * Provides a way to transform expressions + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public interface ExpressionTransformer { + + /** + * Transforms the given expression into another expression + */ + Expression transform(Expression expression); +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java new file mode 100644 index 0000000..41b5acf --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java @@ -0,0 +1,83 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.FieldNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * Represents a field access such as the expression "this.foo". + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class FieldExpression extends Expression { + + private final FieldNode field; + private boolean useRef; + + public FieldExpression(FieldNode field) { + this.field = field; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitFieldExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + return this; + } + + public String getFieldName() { + return field.getName(); + } + + public FieldNode getField() { + return field; + } + + public String getText() { + return "this." + field.getName(); + } + + public boolean isDynamicTyped() { + return field.isDynamicTyped(); + } + + public void setType(ClassNode type) { + super.setType(type); + field.setType(type); + } + + public ClassNode getType() { + return field.getType(); + } + + public void setUseReferenceDirectly(boolean useRef) { + this.useRef = useRef; + } + + public boolean isUseReferenceDirectly() { + return useRef; + } + + public String toString() { + return "field("+getType()+" "+getFieldName()+")"; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/GStringExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/GStringExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/GStringExpression.java new file mode 100644 index 0000000..7ccf355 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/GStringExpression.java @@ -0,0 +1,116 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a String expression which contains embedded values inside + * it such as "hello there ${user} how are you" which is expanded lazily + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class GStringExpression extends Expression { + + private final String verbatimText; + private final List<ConstantExpression> strings; + private final List<Expression> values; + + public GStringExpression(String verbatimText) { + this.verbatimText = verbatimText; + super.setType(ClassHelper.GSTRING_TYPE); + this.strings = new ArrayList<ConstantExpression>(); + this.values = new ArrayList<Expression>(); + } + + public GStringExpression(String verbatimText, List<ConstantExpression> strings, List<Expression> values) { + this.verbatimText = verbatimText; + this.strings = strings; + this.values = values; + super.setType(ClassHelper.GSTRING_TYPE); + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitGStringExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new GStringExpression( + verbatimText, + transformExpressions(strings, transformer, ConstantExpression.class), + transformExpressions(values, transformer)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String toString() { + return super.toString() + "[strings: " + strings + " values: " + values + "]"; + } + + public String getText() { + return verbatimText; + } + + public List<ConstantExpression> getStrings() { + return strings; + } + + public List<Expression> getValues() { + return values; + } + + public void addString(ConstantExpression text) { + if (text == null) { + throw new NullPointerException("Cannot add a null text expression"); + } + strings.add(text); + } + + public void addValue(Expression value) { + // If the first thing is an value, then we need a dummy empty string in front of it so that when we + // toString it they come out in the correct order. + if (strings.isEmpty()) + strings.add(ConstantExpression.EMPTY_STRING); + values.add(value); + } + + public Expression getValue(int idx) { + return values.get(idx); + } + + public boolean isConstantString() { + return values.isEmpty(); + } + + public Expression asConstantString() { + StringBuilder buffer = new StringBuilder(); + for (ConstantExpression expression : strings) { + Object value = expression.getValue(); + if (value != null) { + buffer.append(value); + } + } + return new ConstantExpression(buffer.toString()); + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java new file mode 100644 index 0000000..f4f1001 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java @@ -0,0 +1,47 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.AstToTextHelper; +import org.codehaus.groovy.ast.Parameter; +import org.codehaus.groovy.ast.stmt.Statement; + +/** + * Represents a lambda expression such as e -> e * 2 + * or (x, y) -> x + y or (x, y) -> { x + y } or (int x, int y) -> { x + y } + * + * @author <a href="mailto:[email protected]">Daniel.Sun</a> + * Created on 2016/10/18 + */ +public class LambdaExpression extends ClosureExpression { + public LambdaExpression(Parameter[] parameters, Statement code) { + super(parameters, code); + } + + @Override + public String getText() { + String paramText = AstToTextHelper.getParametersText(this.getParameters()); + if (paramText.length() > 0) { + return "(" + paramText + ") -> { ... }"; + } else { + return "() -> { ... }"; + } + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/ListExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ListExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ListExpression.java new file mode 100644 index 0000000..94ab0d2 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/ListExpression.java @@ -0,0 +1,97 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a list expression [1, 2, 3] which creates a mutable List + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class ListExpression extends Expression { + private final List<Expression> expressions; + private boolean wrapped = false; + + public ListExpression() { + this(new ArrayList<Expression>()); + } + + public ListExpression(List<Expression> expressions) { + this.expressions = expressions; + //TODO: get the type's of the expressions to specify the + // list type to List<X> if possible. + setType(ClassHelper.LIST_TYPE); + } + + public void addExpression(Expression expression) { + expressions.add(expression); + } + + public List<Expression> getExpressions() { + return expressions; + } + + public void setWrapped(boolean value) { + wrapped = value; + } + + public boolean isWrapped() { + return wrapped; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitListExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new ListExpression(transformExpressions(getExpressions(), transformer)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public Expression getExpression(int i) { + return expressions.get(i); + } + + public String getText() { + StringBuilder buffer = new StringBuilder("["); + boolean first = true; + for (Expression expression : expressions) { + if (first) { + first = false; + } else { + buffer.append(", "); + } + + buffer.append(expression.getText()); + } + buffer.append("]"); + return buffer.toString(); + } + + public String toString() { + return super.toString() + expressions; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/MapEntryExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/MapEntryExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/MapEntryExpression.java new file mode 100644 index 0000000..3426fe0 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/MapEntryExpression.java @@ -0,0 +1,68 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.GroovyCodeVisitor; + + +/** + * Represents an entry inside a map expression such as 1 : 2. + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class MapEntryExpression extends Expression { + private Expression keyExpression; + private Expression valueExpression; + + public MapEntryExpression(Expression keyExpression, Expression valueExpression) { + this.keyExpression = keyExpression; + this.valueExpression = valueExpression; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitMapEntryExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new MapEntryExpression(transformer.transform(keyExpression), transformer.transform(valueExpression)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String toString() { + return super.toString() + "(key: " + keyExpression + ", value: " + valueExpression + ")"; + } + + public Expression getKeyExpression() { + return keyExpression; + } + + public Expression getValueExpression() { + return valueExpression; + } + + public void setKeyExpression(Expression keyExpression) { + this.keyExpression = keyExpression; + } + + public void setValueExpression(Expression valueExpression) { + this.valueExpression = valueExpression; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/MapExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/MapExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/MapExpression.java new file mode 100644 index 0000000..0effc80 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/MapExpression.java @@ -0,0 +1,100 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a map expression [1 : 2, "a" : "b", x : y] which creates a mutable Map + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class MapExpression extends Expression { + private final List<MapEntryExpression> mapEntryExpressions; + + public MapExpression() { + this(new ArrayList<MapEntryExpression>()); + } + + public MapExpression(List<MapEntryExpression> mapEntryExpressions) { + this.mapEntryExpressions = mapEntryExpressions; + //TODO: get the type's of the expressions to specify the + // map type to Map<X> if possible. + setType(ClassHelper.MAP_TYPE); + } + + public void addMapEntryExpression(MapEntryExpression expression) { + mapEntryExpressions.add(expression); + } + + public List<MapEntryExpression> getMapEntryExpressions() { + return mapEntryExpressions; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitMapExpression(this); + } + + public boolean isDynamic() { + return false; + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new MapExpression(transformExpressions(getMapEntryExpressions(), transformer, MapEntryExpression.class)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String toString() { + return super.toString() + mapEntryExpressions; + } + + public String getText() { + StringBuilder sb = new StringBuilder(32); + sb.append("["); + int size = mapEntryExpressions.size(); + MapEntryExpression mapEntryExpression = null; + if (size > 0) { + mapEntryExpression = mapEntryExpressions.get(0); + sb.append(mapEntryExpression.getKeyExpression().getText()).append(":").append(mapEntryExpression.getValueExpression().getText()); + for (int i = 1; i < size; i++) { + mapEntryExpression = mapEntryExpressions.get(i); + sb.append(", ").append(mapEntryExpression.getKeyExpression().getText()).append(":").append(mapEntryExpression.getValueExpression().getText()); + if (sb.length() > 120 && i < size - 1) { + sb.append(", ... "); + break; + } + } + } else { + sb.append(":"); + } + sb.append("]"); + return sb.toString(); + } + + public void addMapEntryExpression(Expression keyExpression, Expression valueExpression) { + addMapEntryExpression(new MapEntryExpression(keyExpression, valueExpression)); + } + +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/MethodCall.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/MethodCall.java b/src/main/java/org/codehaus/groovy/ast/expr/MethodCall.java new file mode 100644 index 0000000..e2e889d --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/MethodCall.java @@ -0,0 +1,34 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ASTNode; + +/** + * Interface defining common methods for method calls. + * + * @author Cedric Champeau + * @since 2.1.0 + */ +public interface MethodCall { + ASTNode getReceiver(); + String getMethodAsString(); + Expression getArguments(); + String getText(); +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/MethodCallExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/MethodCallExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/MethodCallExpression.java new file mode 100644 index 0000000..089d930 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/MethodCallExpression.java @@ -0,0 +1,214 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.GenericsType; +import org.codehaus.groovy.ast.GroovyCodeVisitor; +import org.codehaus.groovy.ast.MethodNode; + +/** + * A method call on an object or class + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class MethodCallExpression extends Expression implements MethodCall { + + private Expression objectExpression; + private Expression method; + private Expression arguments; + private boolean spreadSafe = false; + private boolean safe = false; + private boolean implicitThis; + + // type spec for generics + private GenericsType[] genericsTypes = null; + private boolean usesGenerics = false; + + private MethodNode target; + + public static final Expression NO_ARGUMENTS = new TupleExpression(); + + public MethodCallExpression(Expression objectExpression, String method, Expression arguments) { + this(objectExpression,new ConstantExpression(method),arguments); + } + + public MethodCallExpression(Expression objectExpression, Expression method, Expression arguments) { + this.objectExpression = objectExpression; + this.method = method; + if (!(arguments instanceof TupleExpression)){ + this.arguments = new TupleExpression(arguments); + } else { + this.arguments = arguments; + } + //TODO: set correct type here + // if setting type and a methodcall is the last expression in a method, + // then the method will return null if the method itself is not void too! + // (in bytecode after call: aconst_null, areturn) + this.setType(ClassHelper.DYNAMIC_TYPE); + this.setImplicitThis(true); + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitMethodCallExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + MethodCallExpression answer = + new MethodCallExpression(transformer.transform(objectExpression), transformer.transform(method), transformer.transform(arguments)); + answer.setSafe(safe); + answer.setSpreadSafe(spreadSafe); + answer.setImplicitThis(implicitThis); + answer.setGenericsTypes(genericsTypes); + answer.setSourcePosition(this); + answer.setMethodTarget(target); + answer.copyNodeMetaData(this); + return answer; + } + + public Expression getArguments() { + return arguments; + } + + public void setArguments(Expression arguments) { + if (!(arguments instanceof TupleExpression)){ + this.arguments = new TupleExpression(arguments); + } else { + this.arguments = arguments; + } + } + + public Expression getMethod() { + return method; + } + + public void setMethod(Expression method) { + this.method = method; + } + + public ASTNode getReceiver() { + return getObjectExpression(); + } + + /** + * This method returns the method name as String if it is no dynamic + * calculated method name, but a constant. + */ + public String getMethodAsString() { + if (! (method instanceof ConstantExpression)) return null; + ConstantExpression constant = (ConstantExpression) method; + return constant.getText(); + } + + public void setObjectExpression(Expression objectExpression) { + this.objectExpression = objectExpression; + } + + public Expression getObjectExpression() { + return objectExpression; + } + + public String getText() { + String object = objectExpression.getText(); + String meth = method.getText(); + String args = arguments.getText(); + String spread = spreadSafe ? "*" : ""; + String dereference = safe ? "?" : ""; + return object + spread + dereference + "." + meth + args; + } + + /** + * @return is this a safe method call, i.e. if true then if the source object is null + * then this method call will return null rather than throwing a null pointer exception + */ + public boolean isSafe() { + return safe; + } + + public void setSafe(boolean safe) { + this.safe = safe; + } + + public boolean isSpreadSafe() { + return spreadSafe; + } + + public void setSpreadSafe(boolean value) { + spreadSafe = value; + } + + /** + * @return true if no object expression was specified otherwise if + * some expression was specified for the object on which to evaluate + * the method then return false + */ + public boolean isImplicitThis() { + return implicitThis; + } + + public void setImplicitThis(boolean implicitThis) { + this.implicitThis = implicitThis; + } + + public String toString() { + return super.toString() + + "[object: " + + objectExpression + + " method: " + + method + + " arguments: " + + arguments + + "]"; + } + + public GenericsType[] getGenericsTypes() { + return genericsTypes; + } + + public void setGenericsTypes(GenericsType[] genericsTypes) { + usesGenerics = usesGenerics || genericsTypes != null; + this.genericsTypes = genericsTypes; + } + + public boolean isUsingGenerics() { + return usesGenerics; + } + + /** + * Sets a method call target for a direct method call. + * WARNING: A method call made this way will run outside of the MOP! + * @param mn the target as MethodNode, mn==null means no target + */ + public void setMethodTarget(MethodNode mn) { + this.target = mn; + if (mn!=null) { + setType(target.getReturnType()); + } else { + setType(ClassHelper.OBJECT_TYPE); + } + } + + /** + * @return the target as method node if set + */ + public MethodNode getMethodTarget() { + return target; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/MethodPointerExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/MethodPointerExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/MethodPointerExpression.java new file mode 100644 index 0000000..f4d2422 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/MethodPointerExpression.java @@ -0,0 +1,91 @@ +/* + * 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.ast.expr; + +import groovy.lang.Closure; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * Represents a method pointer on an object such as + * foo.&bar which means find the method pointer on foo for the method called "bar" + * which is equivalent to + * <code> + * foo.metaClass.getMethodPointer(foo, "bar") + * </code> + */ +public class MethodPointerExpression extends Expression { + + private final Expression expression; + private final Expression methodName; + + public MethodPointerExpression(Expression expression, Expression methodName) { + this.expression = expression; + this.methodName = methodName; + } + + public Expression getExpression() { + if (expression == null) + return VariableExpression.THIS_EXPRESSION; + else + return expression; + } + + public Expression getMethodName() { + return methodName; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitMethodPointerExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret; + Expression mname = transformer.transform(methodName); + if (expression == null) { + ret = new MethodPointerExpression(VariableExpression.THIS_EXPRESSION, mname); + } else { + ret = new MethodPointerExpression(transformer.transform(expression), mname); + } + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String getText() { + if (expression == null) { + return "&" + methodName; + } else { + return expression.getText() + ".&" + methodName.getText(); + } + } + + public ClassNode getType() { + return ClassHelper.CLOSURE_TYPE.getPlainNodeReference(); + } + + public boolean isDynamic() { + return false; + } + + public Class getTypeClass() { + return Closure.class; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java new file mode 100644 index 0000000..0a8ebc8 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java @@ -0,0 +1,45 @@ +/* + * 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.ast.expr; + +/** + * Represents a method reference or a constructor reference, + * e.g. System.out::println OR Objects::requireNonNull OR Integer::new OR int[]::new + * + * @author <a href="mailto:[email protected]">Daniel.Sun</a> + * Created on 2016/10/19 + */ +public class MethodReferenceExpression extends MethodPointerExpression { + public MethodReferenceExpression(Expression expression, Expression methodName) { + super(expression, methodName); + } + + @Override + public String getText() { + Expression expression = this.getExpression(); + Expression methodName = this.getMethodName(); + + if (expression == null) { + return "::" + methodName; + } else { + return expression.getText() + "::" + methodName.getText(); + } + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/NamedArgumentListExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/NamedArgumentListExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/NamedArgumentListExpression.java new file mode 100644 index 0000000..b53b89b --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/NamedArgumentListExpression.java @@ -0,0 +1,45 @@ +/* + * 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.ast.expr; + +import java.util.List; + +/** + * Represents one or more arguments being passed into a method by name + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class NamedArgumentListExpression extends MapExpression { + + public NamedArgumentListExpression() { + } + + public NamedArgumentListExpression(List<MapEntryExpression> mapEntryExpressions) { + super(mapEntryExpressions); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new NamedArgumentListExpression( + transformExpressions(getMapEntryExpressions(), transformer, MapEntryExpression.class)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/NotExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/NotExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/NotExpression.java new file mode 100644 index 0000000..ec227ee --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/NotExpression.java @@ -0,0 +1,46 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * @author sam + */ +public class NotExpression extends BooleanExpression { + + public NotExpression(Expression expression) { + super(expression); + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitNotExpression(this); + } + + public boolean isDynamic() { + return false; + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new NotExpression(transformer.transform(getExpression())); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/PostfixExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/PostfixExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/PostfixExpression.java new file mode 100644 index 0000000..16d12dc --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/PostfixExpression.java @@ -0,0 +1,75 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; +import org.codehaus.groovy.syntax.Token; + +/** + * Represents a postfix expression like foo++ or bar++ + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class PostfixExpression extends Expression { + + private final Token operation; + private Expression expression; + + public PostfixExpression(Expression expression, Token operation) { + this.operation = operation; + this.expression = expression; + } + + public String toString() { + return super.toString() + "[" + expression + operation + "]"; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitPostfixExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new PostfixExpression(transformer.transform(expression), operation); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public Token getOperation() { + return operation; + } + + public Expression getExpression() { + return expression; + } + + public String getText() { + return "(" + expression.getText() + operation.getText() + ")"; + } + + public ClassNode getType() { + return expression.getType(); + } + +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/PrefixExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/PrefixExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/PrefixExpression.java new file mode 100644 index 0000000..8d8f7b2 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/PrefixExpression.java @@ -0,0 +1,75 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; +import org.codehaus.groovy.syntax.Token; + +/** + * Represents a prefix expression like ++foo or --bar + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class PrefixExpression extends Expression { + + private final Token operation; + private Expression expression; + + public PrefixExpression(Token operation, Expression expression) { + this.operation = operation; + this.expression = expression; + } + + public String toString() { + return super.toString() + "[" + operation + expression + "]"; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitPrefixExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new PrefixExpression(operation, transformer.transform(expression)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public Token getOperation() { + return operation; + } + + public Expression getExpression() { + return expression; + } + + public String getText() { + return "(" + operation.getText() + expression.getText() + ")"; + } + + public ClassNode getType() { + return expression.getType(); + } + +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/PropertyExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/PropertyExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/PropertyExpression.java new file mode 100644 index 0000000..0b22c02 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/PropertyExpression.java @@ -0,0 +1,133 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * Represents a property access such as the expression "foo.bar". + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class PropertyExpression extends Expression { + + private Expression objectExpression; + private final Expression property; + private boolean spreadSafe = false; + private boolean safe = false; + private boolean isStatic = false; + + private boolean implicitThis = false; + + public boolean isStatic() { + return isStatic; + } + + public PropertyExpression(Expression objectExpression, String property) { + this(objectExpression, new ConstantExpression(property), false); + } + + public PropertyExpression(Expression objectExpression, Expression property) { + this(objectExpression, property, false); + } + + public PropertyExpression(Expression objectExpression, Expression property, boolean safe) { + this.objectExpression = objectExpression; + this.property = property; + this.safe = safe; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitPropertyExpression(this); + } + + public boolean isDynamic() { + return true; + } + + public Expression transformExpression(ExpressionTransformer transformer) { + PropertyExpression ret = new PropertyExpression(transformer.transform(objectExpression), + transformer.transform(property), safe); + ret.setSpreadSafe(spreadSafe); + ret.setStatic(isStatic); + ret.setImplicitThis(implicitThis); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public Expression getObjectExpression() { + return objectExpression; + } + + public void setObjectExpression(Expression exp) { + objectExpression=exp; + } + + public Expression getProperty() { + return property; + } + + public String getPropertyAsString() { + if (property==null) return null; + if (! (property instanceof ConstantExpression)) return null; + ConstantExpression constant = (ConstantExpression) property; + return constant.getText(); + } + + public String getText() { + String object = objectExpression.getText(); + String text = property.getText(); + String spread = isSpreadSafe() ? "*" : ""; + String safe = isSafe() ? "?" : ""; + return object + spread + safe + "." + text; + } + + /** + * @return is this a safe navigation, i.e. if true then if the source object is null + * then this navigation will return null + */ + public boolean isSafe() { + return safe; + } + + public boolean isSpreadSafe() { + return spreadSafe; + } + + public void setSpreadSafe(boolean value) { + spreadSafe = value; + } + + public String toString() { + return super.toString() + "[object: " + objectExpression + " property: " + property + "]"; + } + + public void setStatic(boolean aStatic) { + this.isStatic = aStatic; + } + + public boolean isImplicitThis(){ + return implicitThis; + } + + public void setImplicitThis(boolean it) { + implicitThis = it; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java new file mode 100644 index 0000000..9067725 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java @@ -0,0 +1,70 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * Represents a range expression such as for iterating. + * E.g.: + * <pre>for i in 0..10 {...}</pre> + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class RangeExpression extends Expression { + + private final Expression from; + private final Expression to; + private final boolean inclusive; + + public RangeExpression(Expression from, Expression to, boolean inclusive) { + this.from = from; + this.to = to; + this.inclusive = inclusive; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitRangeExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new RangeExpression(transformer.transform(from), transformer.transform(to), inclusive); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public Expression getFrom() { + return from; + } + + public Expression getTo() { + return to; + } + + public boolean isInclusive() { + return inclusive; + } + + public String getText() { + return "(" + from.getText() + + (!isInclusive()? "..<" : ".." ) + + to.getText() + ")"; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/SpreadExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/SpreadExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/SpreadExpression.java new file mode 100644 index 0000000..43a8926 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/SpreadExpression.java @@ -0,0 +1,58 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * Represents a spread expression *x in the list expression [1, *x, 2]. + * + */ +public class SpreadExpression extends Expression { + + private final Expression expression; + + public SpreadExpression(Expression expression) { + this.expression = expression; + } + + public Expression getExpression() { + return expression; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitSpreadExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new SpreadExpression(transformer.transform(expression)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String getText() { + return "*" + expression.getText(); + } + + public ClassNode getType() { + return expression.getType(); + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/SpreadMapExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/SpreadMapExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/SpreadMapExpression.java new file mode 100644 index 0000000..ea6318b --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/SpreadMapExpression.java @@ -0,0 +1,60 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * Represents a spread map expression *:m + * in the map expression [1, *:m, 2, "c":100] + * or in the method invoke expression func(1, *:m, 2, "c":100). + * + */ +public class SpreadMapExpression extends Expression { + + private final Expression expression; + + public SpreadMapExpression(Expression expression) { + this.expression = expression; + } + + public Expression getExpression() { + return expression; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitSpreadMapExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new SpreadMapExpression(transformer.transform(expression)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String getText() { + return "*:" + expression.getText(); + } + + public ClassNode getType() { + return expression.getType(); + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/StaticMethodCallExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/StaticMethodCallExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/StaticMethodCallExpression.java new file mode 100644 index 0000000..679b250 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/StaticMethodCallExpression.java @@ -0,0 +1,95 @@ +/* + * 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.ast.expr; + +import groovy.lang.MetaMethod; +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * A static method call on a class + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class StaticMethodCallExpression extends Expression implements MethodCall { + + private ClassNode ownerType; + private final String method; + private final Expression arguments; + private MetaMethod metaMethod = null; + + public StaticMethodCallExpression(ClassNode type, String method, Expression arguments) { + ownerType = type; + this.method = method; + this.arguments = arguments; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitStaticMethodCallExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new StaticMethodCallExpression(getOwnerType(), method, transformer.transform(arguments)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public ASTNode getReceiver() { + return ownerType; + } + + public String getMethodAsString() { + return method; + } + + public Expression getArguments() { + return arguments; + } + + public String getMethod() { + return method; + } + + public String getText() { + return getOwnerType().getName() + "." + method + arguments.getText(); + } + + public String toString() { + return super.toString() + "[" + getOwnerType().getName() + "#" + method + " arguments: " + arguments + "]"; + } + + public ClassNode getOwnerType() { + return ownerType; + } + + public void setOwnerType(ClassNode ownerType) { + this.ownerType = ownerType; + } + + public void setMetaMethod(MetaMethod metaMethod) { + this.metaMethod = metaMethod; + } + + public MetaMethod getMetaMethod() { + return metaMethod; + } + +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/TernaryExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/TernaryExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/TernaryExpression.java new file mode 100644 index 0000000..a24fd63 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/TernaryExpression.java @@ -0,0 +1,86 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * Represents a ternary expression (booleanExpression) ? expression : expression + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class TernaryExpression extends Expression { + + private final BooleanExpression booleanExpression; + private final Expression trueExpression; + private final Expression falseExpression; + + public TernaryExpression( + BooleanExpression booleanExpression, + Expression trueExpression, + Expression falseExpression) { + this.booleanExpression = booleanExpression; + this.trueExpression = trueExpression; + this.falseExpression = falseExpression; + } + public void visit(GroovyCodeVisitor visitor) { + visitor.visitTernaryExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new TernaryExpression( + (BooleanExpression) transformer.transform(booleanExpression), + transformer.transform(trueExpression), + transformer.transform(falseExpression)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String toString() { + return super.toString() +"[" + booleanExpression + " ? " + trueExpression + " : " + falseExpression + "]"; + } + + public BooleanExpression getBooleanExpression() { + return booleanExpression; + } + + public Expression getFalseExpression() { + return falseExpression; + } + + public Expression getTrueExpression() { + return trueExpression; + } + + public String getText() { + return "(" + + booleanExpression.getText() + + ") ? " + + trueExpression.getText() + + " : " + + falseExpression.getText(); + } + + public ClassNode getType() { + return ClassHelper.OBJECT_TYPE; + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/TupleExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/TupleExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/TupleExpression.java new file mode 100644 index 0000000..113706a --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/TupleExpression.java @@ -0,0 +1,120 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a tuple expression {1, 2, 3} which creates an immutable List + * + * @author <a href="mailto:[email protected]">James Strachan</a> + */ +public class TupleExpression extends Expression implements Iterable<Expression> { + private final List<Expression> expressions; + + public TupleExpression() { + this(0); + } + + public TupleExpression(Expression expr) { + this(1); + addExpression(expr); + } + + public TupleExpression(Expression expr1, Expression expr2) { + this(2); + addExpression(expr1); + addExpression(expr2); + } + + public TupleExpression(Expression expr1, Expression expr2, Expression expr3) { + this(3); + addExpression(expr1); + addExpression(expr2); + addExpression(expr3); + } + + public TupleExpression(int length) { + this.expressions = new ArrayList<Expression>(length); + } + + public TupleExpression(List<Expression> expressions) { + this.expressions = expressions; + } + + public TupleExpression(Expression[] expressionArray) { + this(); + expressions.addAll(Arrays.asList(expressionArray)); + } + + public TupleExpression addExpression(Expression expression) { + expressions.add(expression); + return this; + } + + public List<Expression> getExpressions() { + return expressions; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitTupleExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new TupleExpression(transformExpressions(getExpressions(), transformer)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public Expression getExpression(int i) { + return expressions.get(i); + } + + public String getText() { + StringBuilder buffer = new StringBuilder("("); + boolean first = true; + for (Expression expression : expressions) { + if (first) { + first = false; + } + else { + buffer.append(", "); + } + + buffer.append(expression.getText()); + } + buffer.append(")"); + return buffer.toString(); + } + + public String toString() { + return super.toString() + expressions; + } + + public Iterator<Expression> iterator() { + return Collections.unmodifiableList(expressions).iterator(); + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/UnaryMinusExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/UnaryMinusExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/UnaryMinusExpression.java new file mode 100644 index 0000000..8d1315e --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/UnaryMinusExpression.java @@ -0,0 +1,62 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * @author sam + */ +public class UnaryMinusExpression extends Expression { + + private final Expression expression; + + public UnaryMinusExpression(Expression expression) { + this.expression = expression; + } + + public Expression getExpression() { + return expression; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitUnaryMinusExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new UnaryMinusExpression(transformer.transform(expression)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String getText() { + return expression.getText(); + } + + public ClassNode getType() { + return expression.getType(); + } + + public boolean isDynamic() { + return false; + } + +} http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/ast/expr/UnaryPlusExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/ast/expr/UnaryPlusExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/UnaryPlusExpression.java new file mode 100644 index 0000000..7c3f990 --- /dev/null +++ b/src/main/java/org/codehaus/groovy/ast/expr/UnaryPlusExpression.java @@ -0,0 +1,62 @@ +/* + * 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.ast.expr; + +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.GroovyCodeVisitor; + +/** + * @author Paul King + */ +public class UnaryPlusExpression extends Expression { + + private final Expression expression; + + public UnaryPlusExpression(Expression expression) { + this.expression = expression; + } + + public Expression getExpression() { + return expression; + } + + public void visit(GroovyCodeVisitor visitor) { + visitor.visitUnaryPlusExpression(this); + } + + public Expression transformExpression(ExpressionTransformer transformer) { + Expression ret = new UnaryPlusExpression(transformer.transform(expression)); + ret.setSourcePosition(this); + ret.copyNodeMetaData(this); + return ret; + } + + public String getText() { + return expression.getText(); + } + + public ClassNode getType() { + return expression.getType(); + } + + public boolean isDynamic() { + return false; + } + +} \ No newline at end of file
