/**
* Copyright (c) 2013 Eclipse contributors 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.emf.ecore.xcore.generator;
import org.eclipse.emf.codegen.ecore.genmodel.GenClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xcore.XClass;
import org.eclipse.emf.ecore.xcore.mappings.XcoreMapper;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.xbase.compiler.XbaseCompiler;
import org.eclipse.xtext.xbase.compiler.output.ITreeAppendable;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import com.google.inject.Inject;
public class XcoreCompiler extends XbaseCompiler
{
private final static String REASSIGNED_THIS_IN_LAMBDA = "!reassigned_this_for_lambda!";
@Inject
XcoreMapper mappings;
@Override
protected void reassignThisInClosure(final ITreeAppendable b, JvmType rawClosureType)
{
boolean registerClosureAsThis = rawClosureType instanceof JvmGenericType;
boolean isAlreadyInALambda = b.hasObject(REASSIGNED_THIS_IN_LAMBDA);
if (b.hasObject("this") && !isAlreadyInALambda)
{
Object element = b.getObject("this");
if (element instanceof JvmType)
{
final String proposedName = "<%this%>";
if (!b.hasObject(proposedName))
{
b.declareSyntheticVariable(element, proposedName);
if (b.hasObject("super"))
{
Object superElement = b.getObject("super");
if (superElement instanceof JvmType)
{
b.declareSyntheticVariable(superElement, "<%super%>");
}
}
}
}
else
{
registerClosureAsThis = false;
}
}
if (!isAlreadyInALambda)
{
// add a synthetic marker so we don't reassign this and super more than once.
b.declareSyntheticVariable(REASSIGNED_THIS_IN_LAMBDA, REASSIGNED_THIS_IN_LAMBDA);
}
if (registerClosureAsThis)
{
b.declareVariable(rawClosureType, "this");
}
}
@Override
protected void serialize(JvmTypeReference type, EObject context, ITreeAppendable appendable, boolean withoutConstraints, boolean paramsToWildcard, boolean paramsToObject, boolean allowPrimitives)
{
if (type instanceof JvmParameterizedTypeReference)
{
JvmParameterizedTypeReference jvmParameterizedTypeReference = (JvmParameterizedTypeReference)type;
if (jvmParameterizedTypeReference.getArguments().isEmpty())
{
JvmType referencedType = jvmParameterizedTypeReference.getType();
EObject xcoreElement = mappings.getXcoreElement(referencedType);
if (xcoreElement instanceof XClass)
{
GenClass genClass = (GenClass)mappings.getGen((XClass)xcoreElement);
if (genClass != null && genClass.isExternalInterface())
{
JvmTypeReference superType = IterableExtensions.head(((JvmGenericType)referencedType).getSuperTypes());
if (superType != null)
{
serialize(superType, context, appendable, withoutConstraints, paramsToWildcard, paramsToObject, allowPrimitives);
return;
}
}
}
}
}
super.serialize(type, context, appendable, withoutConstraints, paramsToWildcard, paramsToObject, allowPrimitives);
}
}