/plugins/org.jnario/src/org/jnario/compiler/JnarioCompiler.java
Java | 456 lines | 390 code | 55 blank | 11 comment | 61 complexity | 54b906def399b4f5b8cb7f0d9ccd8da7 MD5 | raw file
Possible License(s): Apache-2.0
- /*******************************************************************************
- * Copyright (c) 2012 BMW Car IT 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.jnario.compiler;
-
- import static com.google.common.collect.Iterables.filter;
- import static com.google.common.collect.Sets.newHashSet;
- import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.getNode;
- import static org.eclipse.xtext.util.Strings.convertToJavaString;
- import static org.jnario.jvmmodel.DoubleArrowSupport.isDoubleArrow;
-
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Set;
-
- import org.eclipse.emf.ecore.EObject;
- import org.eclipse.xtend.core.compiler.XtendCompiler;
- import org.eclipse.xtext.common.types.JvmGenericType;
- import org.eclipse.xtext.common.types.JvmIdentifiableElement;
- import org.eclipse.xtext.common.types.JvmOperation;
- import org.eclipse.xtext.common.types.JvmType;
- import org.eclipse.xtext.common.types.JvmTypeReference;
- import org.eclipse.xtext.nodemodel.INode;
- import org.eclipse.xtext.serializer.ISerializer;
- import org.eclipse.xtext.xbase.XAbstractFeatureCall;
- import org.eclipse.xtext.xbase.XBinaryOperation;
- import org.eclipse.xtext.xbase.XClosure;
- import org.eclipse.xtext.xbase.XExpression;
- import org.eclipse.xtext.xbase.XFeatureCall;
- import org.eclipse.xtext.xbase.XNullLiteral;
- import org.eclipse.xtext.xbase.XSwitchExpression;
- import org.eclipse.xtext.xbase.XbaseFactory;
- import org.eclipse.xtext.xbase.compiler.output.ITreeAppendable;
- import org.jnario.Assertion;
- import org.jnario.MockLiteral;
- import org.jnario.Should;
- import org.jnario.ShouldThrow;
- import org.jnario.lib.Assert;
- import org.jnario.util.MockingSupport;
- import org.jnario.util.SourceAdapter;
-
- import com.google.common.base.Predicate;
- import com.google.common.collect.Iterables;
- import com.google.inject.Inject;
-
- /**
- * @author Sebastian Benz - Initial contribution and API
- */
- public class JnarioCompiler extends XtendCompiler {
-
- @Inject
- private JnarioExpressionHelper expressionHelper;
-
- @Inject ISerializer serializer;
-
- @Override
- public void internalToConvertedExpression(XExpression obj,
- ITreeAppendable appendable) {
- if (obj instanceof Assertion) {
- _toJavaExpression((Assertion) obj, appendable);
- } else if (obj instanceof Should) {
- _toJavaExpression((Should) obj, appendable);
- } else if (obj instanceof ShouldThrow) {
- _toJavaExpression((ShouldThrow) obj, appendable);
- } else if (obj instanceof MockLiteral) {
- _toJavaExpression((MockLiteral) obj, appendable);
- } else {
- super.internalToConvertedExpression(obj, appendable);
- }
- }
-
- @Override
- public void doInternalToJavaStatement(XExpression obj,
- ITreeAppendable appendable, boolean isReferenced) {
- if (obj instanceof Assertion) {
- _toJavaStatement((Assertion) obj, appendable, isReferenced);
- } else if (obj instanceof Should) {
- _toJavaStatement((Should) obj, appendable, isReferenced);
- } else if (obj instanceof ShouldThrow) {
- _toJavaStatement((ShouldThrow) obj, appendable, isReferenced);
- } else if (obj instanceof MockLiteral) {
- _toJavaStatement((MockLiteral) obj, appendable, isReferenced);
- } else
- super.doInternalToJavaStatement(obj, appendable, isReferenced);
- }
-
- public void _toJavaStatement(ShouldThrow should, ITreeAppendable b, boolean isReferenced) {
- if (should.getType() == null || should.getType().getType() == null) {
- return;
- }
- String expectedException = b.declareSyntheticVariable(should, "expectedException");
- b.newLine().append("boolean ").append(expectedException).append(" = false;").newLine();
- String message = b.declareSyntheticVariable(should, "message");
- b.append("String ").append(message).append(" = \"\";");
- b.newLine().append("try{").increaseIndentation();
- toJavaStatement(should.getExpression(), b, false);
- b.newLine().append(message).append(" = \"Expected \" + ")
- .append(should.getType().getType())
- .append(".class.getName() + \" for ")
- .append(javaStringNewLine())
- .append(" ")
- .append(serialize(should.getExpression()).replace("\n", "\n ")).append(javaStringNewLine())
- .append(" with:\"");
- appendValues(should.getExpression(), b, new HashSet<String>());
- b.append(";");
- b.decreaseIndentation().newLine().append("}catch(").increaseIndentation()
- .append(should.getType().getType()).append(" e){").newLine()
- .append(expectedException).append(" = true;")
- .decreaseIndentation().newLine().append("}");
- b.newLine()
- .append(assertType(should))
- .append(".assertTrue(").append(message).append(", ")
- .append(expectedException).append(");");
- }
-
-
-
- public void _toJavaStatement(Should should, ITreeAppendable b,
- boolean isReferenced) {
- _toShouldExpression(should, b, should.isNot());
- }
-
- private void _toShouldExpression(XBinaryOperation should,
- ITreeAppendable b, boolean isNot) {
- if(should.getRightOperand() instanceof XNullLiteral){
- _toShouldBeNullExpression(should, b, isNot);
- }else{
- toShouldBeExpression(should, b, isNot);
- }
- }
-
- private void toShouldBeExpression(XBinaryOperation should,
- ITreeAppendable b, boolean isNot) {
- super._toJavaStatement(should, b, true);
- b.newLine().append(assertType(should));
- if (isNot) {
- b.append(".assertFalse(");
- } else {
- b.append(".assertTrue(");
- }
- generateMessageFor(should, b);
- b.append(" + \"" + javaStringNewLine() + "\", ");
- super._toJavaExpression(should, b);
- b.append(");").newLine();
- }
-
- private void _toShouldBeNullExpression(XBinaryOperation should,
- ITreeAppendable b, boolean isNot) {
- super.toJavaStatement(should.getLeftOperand(), b, true);
- b.newLine().append(assertType(should));
- if (isNot) {
- b.append(".assertNotNull(");
- } else {
- b.append(".assertNull(");
- }
- generateNullMessageFor(should, b);
- b.append(" + \"" + javaStringNewLine() + "\", ");
- super.toJavaExpression(should.getLeftOperand(), b);
- b.append(");").newLine();
- }
-
-
- protected XFeatureCall createFeatureCall(
- JvmIdentifiableElement nullValueMatcher) {
- XFeatureCall featureCall = XbaseFactory.eINSTANCE.createXFeatureCall();
- featureCall.setFeature(nullValueMatcher);
- return featureCall;
- }
-
- protected JvmIdentifiableElement getNullValueMatcher(XBinaryOperation should) {
- return getMethod(should, org.jnario.lib.Should.class.getName(), "nullValue");
- }
-
- protected JvmIdentifiableElement getMethod(XBinaryOperation should, String type, String methodName, String...argumentTypes) {
- JvmGenericType coreMatchersType = (JvmGenericType) jvmType(type, should);
- if(coreMatchersType == null){
- return null;
- }
- Iterable<JvmOperation> operations = Iterables.filter(coreMatchersType.getMembers(), JvmOperation.class);
- for (JvmOperation jvmOperation : operations) {
- if(methodName.equals(jvmOperation.getSimpleName()) && hasArguments(jvmOperation, argumentTypes)){
- return jvmOperation;
- }
- }
- return null;
- }
-
- private boolean hasArguments(JvmOperation jvmOperation,
- String[] argumentTypes) {
- if(jvmOperation.getParameters().size() != argumentTypes.length){
- return false;
- }
- for (int i = 0; i < argumentTypes.length; i++) {
- String argumentType = argumentTypes[i];
- JvmTypeReference actual = getTypeComputationServices().getTypeReferences().getTypeForName(argumentType, jvmOperation);
- JvmTypeReference expected = jvmOperation.getParameters().get(i).getParameterType();
- // System.out.println(expected.getQualifiedName() + "=>" + actual.getQualifiedName());
- if(!expected.getQualifiedName().equals(actual.getQualifiedName())){
- return false;
- }
- }
- return true;
- }
-
- private String javaStringNewLine() {
- return convertToJavaString("\n");
- }
-
- public void _toJavaExpression(MockLiteral expr, ITreeAppendable b) {
- JvmType mockito = getTypeComputationServices().getTypeReferences().findDeclaredType(MockingSupport.CLASS_NAME, expr);
- b.append(mockito).append(".mock(");
- b.append(expr.getType()).append(".class");
- b.append(")");
- }
-
- public void _toJavaStatement(MockLiteral expr, ITreeAppendable b, boolean isReferenced) {
- generateComment(expr, b, isReferenced);
- }
-
- public void _toJavaExpression(Should should, ITreeAppendable b) {
- b.append("true");
- }
-
- public void _toJavaExpression(ShouldThrow should, ITreeAppendable b) {
- b.append("true");
- }
-
- public void _toJavaStatement(Assertion assertion, ITreeAppendable b,
- boolean isReferenced) {
- if (assertion.getExpression() == null) {
- return;
- }
- generateSingleAssertion(assertion.getExpression(), b);
- }
-
- public void _toJavaExpression(Assertion assertion, ITreeAppendable b) {
- b.append("true");
- }
-
- private void generateSingleAssertion(XExpression expr, ITreeAppendable b) {
- toJavaStatement(expr, b, true);
- b.newLine();
- b.append(assertType(expr));
- b.append(".assertTrue(");
- generateMessageFor(expr, b);
- b.append(" + \"" + javaStringNewLine() + "\", ");
- toJavaExpression(expr, b);
- b.append(");");
- b.newLine();
- }
-
- private JvmType assertType(XExpression expr) {
- return jvmType(Assert.class, expr);
- }
-
- private boolean isVoid(XExpression expr) {
- JvmTypeReference type = getType(expr);
- return getTypeComputationServices().getTypeReferences().is(type, Void.TYPE);
- }
-
- private JvmType jvmType(Class<?> type, EObject context) {
- return jvmType(type.getName(), context);
- }
-
- private JvmType jvmType(String type, EObject context) {
- JvmTypeReference jvmTypeReference = getTypeComputationServices().getTypeReferences().getTypeForName(type, context);
- if(jvmTypeReference == null){
- return null;
- }
- return jvmTypeReference.getType();
- }
-
- public void generateMessageFor(Should should, ITreeAppendable b) {
- b.append("\"\\nExpected ");
- b.append(serialize(should));
- b.append(" but\"");
- Set<String> valueExpressions = newHashSet();
-
- XExpression left = should.getLeftOperand();
- toLiteralValue(left, b, valueExpressions);
- appendValues(left, b, valueExpressions);
-
- XExpression right = should.getRightOperand();
- toLiteralValue(right, b, valueExpressions);
- appendValues(right, b, valueExpressions);
-
- if (valueExpressions.isEmpty()) {
- b.append(" + \" did not.\"");
- }
- }
-
- private void generateNullMessageFor(XBinaryOperation should, ITreeAppendable b) {
- b.append("\"\\nExpected ");
- b.append(serialize(should));
- b.append("\\n but is \"");
- toValue(should.getLeftOperand(), b);
- }
-
- private void generateMessageFor(XExpression expression, ITreeAppendable b) {
- b.append("\"\\nExpected ");
- b.append(serialize(expression));
- b.append(" but\"");
- Set<String> valueExpressions = newHashSet();
- appendValues(expression, b, valueExpressions);
- if (valueExpressions.isEmpty()) {
- b.append(" + \" did not.\"");
- }
- }
-
- private void appendValues(XExpression expression, ITreeAppendable b,
- Set<String> valueExpressions) {
- Iterator<XExpression> subExpressions = allSubExpressions(expression);
- if (subExpressions.hasNext()) {
- while (subExpressions.hasNext()) {
- XExpression subExpression = subExpressions.next();
- appendActualValues(subExpression, b, valueExpressions);
- }
- } else {
- toLiteralValue(expression, b, valueExpressions);
- }
- }
-
- protected String serialize(XExpression expression) {
- INode node = findNode(expression);
- if(node == null){
- return "";
- }
- String result = node.getText();
- result = result.trim();
- result = removeSurroundingParentheses(result);
- return convertToJavaString(result);
- }
-
- private INode findNode(XExpression expression) {
- INode node = getNode(expression);
- if(node != null) {
- return node;
- }
- EObject source = SourceAdapter.find(expression);
- while(node == null && isExpressions(source)){
- node = getNode(source);
- source = source.eContainer();
- }
- return node;
- }
-
- private boolean isExpressions(EObject source) {
- return source != null && source instanceof XExpression;
- }
-
- protected String removeSurroundingParentheses(String result) {
- if (result.startsWith("(") && result.endsWith(")")) {
- result = result.substring(1, result.length() - 1);
- }
- return result.trim();
- }
-
- protected void appendActualValues(XExpression expression,
- ITreeAppendable b, Set<String> valueExpressions) {
- toLiteralValue(expression, b, valueExpressions);
- Iterator<XExpression> subExpressions = allSubExpressions(expression);
- while (subExpressions.hasNext()) {
- XExpression subExpression = subExpressions.next();
- appendActualValues(subExpression, b, valueExpressions);
- }
- }
-
- protected Iterator<XExpression> allSubExpressions(XExpression expression) {
- Predicate<XExpression> noSwitchCases = new Predicate<XExpression>() {
- public boolean apply(XExpression e) {
- return !(e.eContainer() instanceof XSwitchExpression);
- }
- };
- Predicate<XExpression> noLiteralExpressions = new Predicate<XExpression>() {
- public boolean apply(XExpression expr) {
- return !expressionHelper.isLiteral(expr);
- }
- };
- Iterable<XExpression> subExpressions = filter(expression.eContents(), XExpression.class);
-
- subExpressions = filter(subExpressions, noLiteralExpressions);
- subExpressions = filter(subExpressions, noSwitchCases);
- return subExpressions.iterator();
- }
-
- protected void toLiteralValue(XExpression expression, ITreeAppendable b,
- Set<String> valueMappings) {
- if (expressionHelper.isLiteral(expression)) {
- return;
- }
- if (isVoid(expression)) {
- return;
- }
- if(isClosure(expression)){
- return;
- }
- toValue(expression, b, valueMappings);
- }
-
- private void toValue(XExpression expression, ITreeAppendable b,
- Set<String> valueMappings) {
- String expr = serialize(expression);
- if (expr.isEmpty() || valueMappings.contains(expr)) {
- return;
- }
- valueMappings.add(expr);
- b.append("\n + \"\\n ");
- b.append(expr);
- b.append(" is \"");
- toValue(expression, b);
- }
-
- private void toValue(XExpression expression, ITreeAppendable b) {
- b.append(" + new ");
- b.append("org.hamcrest.StringDescription");
- b.append("().appendValue(");
- toJavaExpression(expression, b);
- b.append(").toString()");
- }
-
- private boolean isClosure(XExpression expression) {
- JvmTypeReference type = getType(expression);
- return type.getQualifiedName().startsWith("org.eclipse.xtext.xbase.lib.Functions");
- }
-
- @Override
- protected boolean isVariableDeclarationRequired(XExpression expr,
- ITreeAppendable b) {
- if (expr instanceof Assertion) {
- return false;
- }
- return super.isVariableDeclarationRequired(expr, b);
- }
-
-
- @Override
- protected void _toJavaStatement(XAbstractFeatureCall expr,
- ITreeAppendable b, boolean isReferenced) {
- if(!isDoubleArrow(expr)){
- super._toJavaStatement(expr, b, isReferenced);
- return;
- }
- XBinaryOperation doubleArrow = (XBinaryOperation) expr;
- if(doubleArrow.getRightOperand() instanceof XClosure){
- super._toJavaStatement(expr, b, isReferenced);
- return;
- }else{
- _toShouldExpression((XBinaryOperation) expr, b, false);
- }
- }
-
- }