org.eclipse.xtext.xbase.util.XExpressionHelper Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.xbase.util;
import static org.eclipse.xtext.util.Strings.*;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.xtext.common.types.JvmAnnotationReference;
import org.eclipse.xtext.common.types.JvmAnnotationTarget;
import org.eclipse.xtext.common.types.JvmConstructor;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmExecutable;
import org.eclipse.xtext.common.types.JvmIdentifiableElement;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.common.types.util.TypeReferences;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.xbase.XAbstractFeatureCall;
import org.eclipse.xtext.xbase.XAssignment;
import org.eclipse.xtext.xbase.XBinaryOperation;
import org.eclipse.xtext.xbase.XBooleanLiteral;
import org.eclipse.xtext.xbase.XClosure;
import org.eclipse.xtext.xbase.XCollectionLiteral;
import org.eclipse.xtext.xbase.XConstructorCall;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.XNullLiteral;
import org.eclipse.xtext.xbase.XNumberLiteral;
import org.eclipse.xtext.xbase.XPostfixOperation;
import org.eclipse.xtext.xbase.XStringLiteral;
import org.eclipse.xtext.xbase.XTypeLiteral;
import org.eclipse.xtext.xbase.annotations.xAnnotations.XAnnotation;
import org.eclipse.xtext.xbase.lib.BooleanExtensions;
import org.eclipse.xtext.xbase.lib.ByteExtensions;
import org.eclipse.xtext.xbase.lib.CharacterExtensions;
import org.eclipse.xtext.xbase.lib.DoubleExtensions;
import org.eclipse.xtext.xbase.lib.FloatExtensions;
import org.eclipse.xtext.xbase.lib.Inline;
import org.eclipse.xtext.xbase.lib.IntegerExtensions;
import org.eclipse.xtext.xbase.lib.LongExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.lib.ReassignFirstArgument;
import org.eclipse.xtext.xbase.lib.ShortExtensions;
import org.eclipse.xtext.xbase.scoping.featurecalls.OperatorMapping;
import com.google.inject.Inject;
/**
* @author Jan Koehnlein - Initial contribution and API
*/
public class XExpressionHelper {
@Inject
private TypeReferences typeReferences;
@Inject
private OperatorMapping operatorMapping;
/**
* @return whether the expression itself (not its children) possibly causes a side-effect
*/
public boolean hasSideEffects(XExpression expr) {
if (expr instanceof XClosure
|| expr instanceof XStringLiteral
|| expr instanceof XTypeLiteral
|| expr instanceof XBooleanLiteral
|| expr instanceof XNumberLiteral
|| expr instanceof XNullLiteral
|| expr instanceof XAnnotation
)
return false;
if(expr instanceof XCollectionLiteral) {
for(XExpression element: ((XCollectionLiteral)expr).getElements()) {
if(hasSideEffects(element))
return true;
}
return false;
}
if (expr instanceof XAbstractFeatureCall) {
XAbstractFeatureCall featureCall = (XAbstractFeatureCall) expr;
return hasSideEffects(featureCall, true);
}
if (expr instanceof XConstructorCall) {
XConstructorCall constrCall = (XConstructorCall) expr;
return findPureAnnotation(constrCall.getConstructor()) == null;
}
return true;
}
public boolean hasSideEffects(XAbstractFeatureCall featureCall, boolean inspectContents) {
if (featureCall instanceof XBinaryOperation) {
XBinaryOperation binaryOperation = (XBinaryOperation) featureCall;
if (binaryOperation.isReassignFirstArgument()) {
return true;
}
}
if (featureCall instanceof XAssignment) {
return true;
}
if (featureCall.isPackageFragment() || featureCall.isTypeLiteral()) {
return false;
}
final JvmIdentifiableElement feature = featureCall.getFeature();
if (feature == null || feature.eIsProxy())
return true; // linking problems ... could be anything
if (feature instanceof JvmConstructor) { //super() and this()
return true;
}
if (feature instanceof JvmOperation) {
JvmOperation jvmOperation = (JvmOperation) feature;
if (findPureAnnotation(jvmOperation) == null) {
return true;
} else {
if(inspectContents) {
for (XExpression param : featureCall.getActualArguments()) {
if (hasSideEffects(param))
return true;
}
}
}
}
return false;
}
public JvmAnnotationReference findInlineAnnotation(XAbstractFeatureCall featureCall) {
final JvmIdentifiableElement feature = featureCall.getFeature();
return findInlineAnnotation(feature);
}
public JvmAnnotationReference findInlineAnnotation(final JvmIdentifiableElement feature) {
if (feature instanceof JvmAnnotationTarget) {
return findAnnotation((JvmAnnotationTarget) feature, Inline.class.getName());
}
return null;
}
public JvmAnnotationReference findCompoundAssignmentAnnotation(XAbstractFeatureCall featureCall) {
final JvmIdentifiableElement feature = featureCall.getFeature();
return findReassignFirstArgumentAnnotation(feature);
}
public JvmAnnotationReference findReassignFirstArgumentAnnotation(JvmIdentifiableElement feature) {
if (feature instanceof JvmAnnotationTarget) {
return findAnnotation((JvmAnnotationTarget) feature, ReassignFirstArgument.class.getName());
}
return null;
}
public JvmAnnotationReference findPureAnnotation(JvmExecutable featureCall) {
return findAnnotation(featureCall, Pure.class.getName());
}
protected JvmAnnotationReference findAnnotation(JvmAnnotationTarget feature, String annotationType) {
if (feature == null)
return null;
if (annotationType == null)
throw new NullPointerException();
List annotations = feature.getAnnotations();
for (JvmAnnotationReference annotation : annotations) {
if (annotationType.equals(annotation.getAnnotation().getQualifiedName())) {
return annotation;
}
}
return null;
}
public String getAndOperator() {
return "&&";
}
public String getOrOperator() {
return "||";
}
public String getElvisOperator() {
return "?:";
}
public boolean isGetAndAssign(XAbstractFeatureCall featureCall) {
if (!(featureCall instanceof XPostfixOperation)) {
return false;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.MINUS_MINUS, DoubleExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.PLUS_PLUS, DoubleExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.MINUS_MINUS, FloatExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.PLUS_PLUS, FloatExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.MINUS_MINUS, LongExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.PLUS_PLUS, LongExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.MINUS_MINUS, IntegerExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.PLUS_PLUS, IntegerExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.MINUS_MINUS, ShortExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.PLUS_PLUS, ShortExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.MINUS_MINUS, CharacterExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.PLUS_PLUS, CharacterExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.MINUS_MINUS, ByteExtensions.class)) {
return true;
}
if (isOperatorFromExtension(featureCall, OperatorMapping.PLUS_PLUS, ByteExtensions.class)) {
return true;
}
return false;
}
public boolean isShortCircuitOperation(XAbstractFeatureCall featureCall) {
if (featureCall instanceof XBinaryOperation) {
if (isOperatorFromExtension(featureCall, OperatorMapping.ELVIS, ObjectExtensions.class))
return true;
else
return isBooleanAndOrOr(featureCall);
}
return false;
}
public boolean isBooleanAndOrOr(XAbstractFeatureCall featureCall) {
return isOperatorFromExtension(featureCall, OperatorMapping.AND, BooleanExtensions.class)
|| isOperatorFromExtension(featureCall, OperatorMapping.OR, BooleanExtensions.class);
}
public boolean isOperatorFromExtension(XExpression expression, QualifiedName operatorSymbol, Class> definingExtensionClass) {
return expression instanceof XAbstractFeatureCall && isOperatorFromExtension((XAbstractFeatureCall) expression, operatorSymbol, definingExtensionClass);
}
public boolean isOperatorFromExtension(XAbstractFeatureCall featureCall, QualifiedName operatorSymbol, Class> definingExtensionClass) {
return isOperatorFromExtension(featureCall, featureCall.getConcreteSyntaxFeatureName(), operatorSymbol, definingExtensionClass);
}
public boolean isOperatorFromExtension(XAbstractFeatureCall featureCall, String concreteSyntax, QualifiedName operatorSymbol, Class> definingExtensionClass) {
if(!equal(concreteSyntax, operatorSymbol.getLastSegment()))
return false;
List methodNames = getMethodNames(featureCall, operatorSymbol);
JvmDeclaredType definingJvmType = (JvmDeclaredType) typeReferences.findDeclaredType(definingExtensionClass, featureCall);
if (definingJvmType == null)
return false;
JvmIdentifiableElement feature = featureCall.getFeature();
if (definingJvmType != feature.eContainer()) {
return false;
}
for (QualifiedName methodName : methodNames) {
if (methodName.getLastSegment().equals(feature.getSimpleName())) {
return true;
}
}
return false;
}
protected List getMethodNames(XAbstractFeatureCall featureCall, QualifiedName operatorSymbol) {
List methodNames = new ArrayList();
methodNames.add(operatorMapping.getMethodName(operatorSymbol));
if (featureCall instanceof XBinaryOperation) {
XBinaryOperation binaryOperation = (XBinaryOperation) featureCall;
if (binaryOperation.isReassignFirstArgument()) {
QualifiedName simpleOperator = operatorMapping.getSimpleOperator(operatorSymbol);
if (simpleOperator != null) {
methodNames.add(operatorMapping.getMethodName(simpleOperator));
}
}
}
return methodNames;
}
public boolean isInlined(XAbstractFeatureCall call) {
return findInlineAnnotation(call) != null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy