Skip to content

Commit

Permalink
[lang] Generate @inline annotations.
Browse files Browse the repository at this point in the history
close #375

Signed-off-by: Stéphane Galland <galland@arakhne.org>
  • Loading branch information
gallandarakhneorg committed Aug 19, 2016
1 parent 6cacb5b commit b31758c
Show file tree
Hide file tree
Showing 3 changed files with 413 additions and 0 deletions.
Expand Up @@ -97,8 +97,17 @@
import org.eclipse.xtext.serializer.sequencer.IContextFinder;
import org.eclipse.xtext.xbase.XBlockExpression;
import org.eclipse.xtext.xbase.XBooleanLiteral;
import org.eclipse.xtext.xbase.XCastedExpression;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.XInstanceOfExpression;
import org.eclipse.xtext.xbase.XNullLiteral;
import org.eclipse.xtext.xbase.XNumberLiteral;
import org.eclipse.xtext.xbase.XReturnExpression;
import org.eclipse.xtext.xbase.XStringLiteral;
import org.eclipse.xtext.xbase.XTypeLiteral;
import org.eclipse.xtext.xbase.compiler.GeneratorConfig;
import org.eclipse.xtext.xbase.compiler.ImportManager;
import org.eclipse.xtext.xbase.compiler.output.FakeTreeAppendable;
import org.eclipse.xtext.xbase.compiler.output.ITreeAppendable;
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor;
import org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociator;
Expand Down Expand Up @@ -1313,6 +1322,12 @@ protected void transform(final XtendFunction source, final JvmGenericType contai
operation.getAnnotations().add(annotationClassRef(FiredEvent.class, firedEvents));
}

// Add @Inline annotation
if (this.expressionHelper.isInlinableOperation(operation, expression)
&& this.annotationFinder.findAnnotation(operation, Inline.class) == null) {
appendInlineAnnotation(operation, expression);
}

// 1. Ensure that the Java annotations related to the default value are really present.
// They may be not present if the generated action is a specific version of an inherited
// action with default values for parameters.
Expand Down Expand Up @@ -2373,6 +2388,90 @@ protected void appendInlineAnnotation(JvmOperation operation, String inlineExpre
operation.getAnnotations().add(annotationReference);
}

/** Append the inline annotation to the given operation.
*
* @param operation the operation to annotate.
* @param expression the expression of the operation.
* @see SARLExpressionHelper#isInlinableOperation(JvmOperation, XExpression)
*/
protected void appendInlineAnnotation(JvmOperation operation, XExpression expression) {
XExpression content = expression;
while (content instanceof XBlockExpression) {
final XBlockExpression blockExpr = (XBlockExpression) content;
if (blockExpr.getExpressions().size() == 1) {
content = blockExpr.getExpressions().get(0);
} else {
content = null;
}
}
final ImportManager imports = new ImportManager();
final ITreeAppendable result = new FakeTreeAppendable(imports, "", " "); //$NON-NLS-1$//$NON-NLS-2$
if (appendInlineAnnotation(operation, content, result)) {
final List<String> importedTypes = imports.getImports();
final JvmTypeReference[] importArray = new JvmTypeReference[importedTypes.size()];
for (int i = 0; i < importArray.length; ++i) {
importArray[i] = this.typeReferences.getTypeForName(importedTypes.get(i), expression);
}
appendInlineAnnotation(operation, result.toString(), importArray);
}
}

/** Append the inline annotation to the given operation.
*
* @param operation the operation to annotate.
* @param expression the expression of the operation.
* @param output the inline code.
*/
@SuppressWarnings("checkstyle:npathcomplexity")
private boolean appendInlineAnnotation(JvmOperation operation, XExpression expression, ITreeAppendable output) {
if (expression instanceof XBooleanLiteral) {
final XBooleanLiteral expr = (XBooleanLiteral) expression;
output.append(Boolean.toString(expr.isIsTrue()));
return true;
}
if (expression instanceof XNullLiteral) {
output.append("null"); //$NON-NLS-1$
return true;
}
if (expression instanceof XNumberLiteral) {
final XNumberLiteral expr = (XNumberLiteral) expression;
output.append(expr.getValue());
return true;
}
if (expression instanceof XStringLiteral) {
final XStringLiteral expr = (XStringLiteral) expression;
output.append("\"" //$NON-NLS-1$
+ org.eclipse.xtext.util.Strings.convertToJavaString(expr.getValue())
+ "\""); //$NON-NLS-1$
return true;
}
if (expression instanceof XTypeLiteral) {
final XTypeLiteral expr = (XTypeLiteral) expression;
output.append(expr.getType());
output.append(".class"); //$NON-NLS-1$
return true;
}
if (expression instanceof XReturnExpression) {
return appendInlineAnnotation(operation, ((XReturnExpression) expression).getExpression(), output);
}
if (expression instanceof XCastedExpression) {
final XCastedExpression expr = (XCastedExpression) expression;
output.append("("); //$NON-NLS-1$
output.append(expr.getType().getType());
output.append(")"); //$NON-NLS-1$
appendInlineAnnotation(operation, expr.getTarget(), output);
return true;
}
if (expression instanceof XInstanceOfExpression) {
final XInstanceOfExpression expr = (XInstanceOfExpression) expression;
appendInlineAnnotation(operation, expr.getExpression(), output);
output.append(" instanceof "); //$NON-NLS-1$
output.append(expr.getType().getType());
return true;
}
return false;
}

/** Create an annotation with classes as values.
*
* @param type - the type of the annotation.
Expand Down
Expand Up @@ -34,10 +34,17 @@
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.xbase.XAbstractFeatureCall;
import org.eclipse.xtext.xbase.XBlockExpression;
import org.eclipse.xtext.xbase.XBooleanLiteral;
import org.eclipse.xtext.xbase.XCastedExpression;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.XInstanceOfExpression;
import org.eclipse.xtext.xbase.XNullLiteral;
import org.eclipse.xtext.xbase.XNumberLiteral;
import org.eclipse.xtext.xbase.XReturnExpression;
import org.eclipse.xtext.xbase.XStringLiteral;
import org.eclipse.xtext.xbase.XSynchronizedExpression;
import org.eclipse.xtext.xbase.XTypeLiteral;
import org.eclipse.xtext.xbase.lib.Inline;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.typesystem.util.CommonTypeComputationServices;

Expand Down Expand Up @@ -157,4 +164,58 @@ public boolean isPurableOperation(JvmOperation operation, XExpression body) {
return (name != null && this.pattern.matcher(name).find()) || !hasSideEffects(body);
}

/** Replies if the given expression could be inline.
*
* @param expr - the body of the operation.
* @return <code>true</code> if one of the components of the given expression could be inline;
* otherwise <code>false</code>.
* @see Inline
*/
@SuppressWarnings("checkstyle:npathcomplexity")
public boolean isInlinableOperation(XExpression expr) {
if (expr != null) {
XExpression content = expr;
while (content instanceof XBlockExpression) {
final XBlockExpression blockExpr = (XBlockExpression) content;
if (blockExpr.getExpressions().size() == 1) {
content = blockExpr.getExpressions().get(0);
} else {
content = null;
}
}
if (content instanceof XBooleanLiteral
|| content instanceof XNullLiteral
|| content instanceof XNumberLiteral
|| content instanceof XStringLiteral
|| content instanceof XTypeLiteral) {
return true;
}
if (content instanceof XReturnExpression) {
return isInlinableOperation(((XReturnExpression) content).getExpression());
}
if (content instanceof XCastedExpression) {
return isInlinableOperation(((XCastedExpression) content).getTarget());
}
if (content instanceof XInstanceOfExpression) {
return isInlinableOperation(((XInstanceOfExpression) content).getExpression());
}
}
return false;
}

/** Replies if the given body could be inline.
*
* @param operation - the operation to test.
* @param body - the body of the operation.
* @return <code>true</code> if one of the components of the given expression could be inline;
* otherwise <code>false</code>.
* @see Inline
*/
public boolean isInlinableOperation(JvmOperation operation, XExpression body) {
if (operation != null && !operation.isAbstract()) {
return isInlinableOperation(body);
}
return false;
}

}

0 comments on commit b31758c

Please sign in to comment.