use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method transformCallableBridge.
public JCExpression transformCallableBridge(Tree.StaticMemberOrTypeExpression expr, Value functional, Type expectedType) {
ParameterList paramList = new ParameterList();
// expr is a SAM
// expectedType is a Callable
TypedReference samRef = checkForFunctionalInterface(expr.getTypeModel());
TypedDeclaration samDecl = samRef.getDeclaration();
if (samDecl instanceof Value) {
Parameter param = new Parameter();
Value paramModel = new Value();
param.setModel(paramModel);
param.setName("arg0");
paramModel.setName("arg0");
paramModel.setType(samRef.getType());
paramModel.setUnboxed(samDecl.getUnboxed());
// FIXME: other stuff like erasure?
paramList.getParameters().add(param);
} else {
int i = 0;
for (Parameter samParam : ((Function) samDecl).getFirstParameterList().getParameters()) {
TypedReference typedSamParam = samRef.getTypedParameter(samParam);
Parameter param = new Parameter();
Value paramModel = new Value();
param.setModel(paramModel);
param.setName("arg" + i);
paramModel.setName("arg" + i);
paramModel.setType(typedSamParam.getFullType());
// FIXME: other stuff like erasure?
paramModel.setUnboxed(typedSamParam.getDeclaration().getUnboxed());
paramList.getParameters().add(param);
i++;
}
}
// FIXME: this is cheating we should be assembling it from the SAM type
Type callableType = expectedType.getSupertype(typeFact().getCallableDeclaration());
return CallableBuilder.methodReference(gen(), expr, paramList, expectedType, callableType, false);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class MethodDefinitionBuilder method getNonWideningParam.
public NonWideningParam getNonWideningParam(TypedReference typedRef, WideningRules wideningRules) {
TypedDeclaration nonWideningDecl = null;
int flags = 0;
long modifiers = 0;
Type nonWideningType;
FunctionOrValue mov = (FunctionOrValue) typedRef.getDeclaration();
if (Decl.isValue(mov)) {
TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef).resolveAliases();
nonWideningDecl = nonWideningTypedRef.getDeclaration();
} else {
// Stef: So here's the thing. I know this is wrong for Function where we should do getFullType(), BUT
// lots of methods call this and then feed the output into AT.makeJavaType(TypedDeclaration typeDecl, Type type, int flags)
// which adds the Callable type, so if we fix it here we have to remove it from there and there's lots of callers of that
// function which rely on its behaviour and frankly I've had enough of this refactoring, so a few callers of this function
// have to add the Callable back. It sucks, yeah, but so far it works, which is amazing enough that I don't want to touch it
// any more. More ambitious/courageous people are welcome to fix this properly.
nonWideningType = typedRef.getType().resolveAliases();
nonWideningDecl = mov;
}
if (!CodegenUtil.isUnBoxed(nonWideningDecl))
flags |= AbstractTransformer.JT_NO_PRIMITIVES;
// make sure we don't accidentally narrow value parameters that would be erased in the topmost declaration
if (wideningRules != WideningRules.NONE && mov instanceof Value) {
TypedDeclaration refinedParameter = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(mov);
if (refinedParameter != null && refinedParameter instanceof Value && ((Value) refinedParameter).getInitializerParameter() != null && gen.isJavaVariadic(((Value) refinedParameter).getInitializerParameter())) {
modifiers |= Flags.VARARGS;
}
// mixin bridge methods have the same rules as when refining stuff except they are their own refined decl
if (wideningRules == WideningRules.FOR_MIXIN || !Decl.equal(refinedParameter, mov)) {
Type refinedParameterType;
// in the refined parameter type
if (refinedParameter instanceof Function)
refinedParameterType = refinedParameter.appliedTypedReference(null, Collections.<Type>emptyList()).getFullType();
else
refinedParameterType = refinedParameter.getType();
// if the supertype method itself got erased to Object, we can't do better than this
if (gen.willEraseToObject(refinedParameterType) && !gen.willEraseToBestBounds(mov))
nonWideningType = gen.typeFact().getObjectType();
else if (CodegenUtil.isRaw(refinedParameter)) {
flags |= AbstractTransformer.JT_RAW;
} else {
flags |= AbstractTransformer.JT_NARROWED;
}
if ((flags & AbstractTransformer.JT_RAW) == 0 && !Decl.equal(refinedParameter, mov) && implementsRawParameter(mov)) {
flags |= AbstractTransformer.JT_RAW;
}
}
}
// keep in sync with gen.willEraseToBestBounds()
if (wideningRules != WideningRules.NONE && (gen.typeFact().isUnion(nonWideningType) || gen.typeFact().isIntersection(nonWideningType))) {
final Type refinedType = ((TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(nonWideningDecl)).getType();
if (refinedType.isTypeParameter() && !refinedType.getSatisfiedTypes().isEmpty()) {
nonWideningType = refinedType.getSatisfiedTypes().get(0);
// Could be parameterized, and type param won't be in scope, so have to go raw
flags |= AbstractTransformer.JT_RAW;
}
}
// this is to be done on the parameter's containing method, to see if that method must have raw parameters
if (mov.isParameter() && mov.getContainer() instanceof Declaration && gen.rawParameters((Declaration) mov.getContainer())) {
flags |= AbstractTransformer.JT_RAW;
}
return new NonWideningParam(flags, modifiers, nonWideningType, nonWideningDecl);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class MethodDefinitionBuilder method implementsRawParameter.
private boolean implementsRawParameter(FunctionOrValue decl) {
if (ModelUtil.containsRawType(decl.getType()))
return true;
// Taken pretty much straight from JvmBackendUtil.getTopmostRefinement
Functional func = (Functional) JvmBackendUtil.getParameterized((FunctionOrValue) decl);
if (func == null || func instanceof TypedDeclaration == false)
return false;
Declaration kk = getFirstRefinedDeclaration((TypedDeclaration) func);
// error recovery
if (kk instanceof Functional == false)
return false;
Functional refinedFunc = (Functional) kk;
// shortcut if the functional doesn't override anything
if (ModelUtil.equal((Declaration) refinedFunc, (Declaration) func)) {
return false;
}
if (func.getParameterLists().size() != refinedFunc.getParameterLists().size()) {
// invalid input
return false;
}
for (int ii = 0; ii < func.getParameterLists().size(); ii++) {
if (func.getParameterLists().get(ii).getParameters().size() != refinedFunc.getParameterLists().get(ii).getParameters().size()) {
// invalid input
return false;
}
// find the index of the parameter in the declaration
int index = 0;
for (Parameter px : func.getParameterLists().get(ii).getParameters()) {
if (px.getModel() == null || px.getModel().equals(decl)) {
// And return the corresponding parameter from the refined declaration
FunctionOrValue refinedDecl = refinedFunc.getParameterLists().get(ii).getParameters().get(index).getModel();
return implementsRawParameter(refinedDecl);
}
index++;
}
continue;
}
// invalid input
return false;
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class Naming method makeDefaultedParamMethod.
JCExpression makeDefaultedParamMethod(JCExpression qualifier, Parameter param) {
// TODO Can we merge this into makeName(..., NA_DPM) ?
if (!Strategy.hasDefaultParameterValueMethod(param)) {
throw new BugException();
}
Declaration decl = param.getDeclaration();
String methodName = getDefaultedParamMethodName(decl, param);
switch(Strategy.defaultParameterMethodOwner(param.getModel())) {
case SELF:
{
// method not within interface
Declaration container = param.getDeclaration().getRefinedDeclaration();
if (!container.isToplevel()) {
container = (Declaration) container.getContainer();
}
JCExpression className = makeTypeDeclarationExpression(qualifier, (TypeDeclaration) container, DeclNameFlag.COMPANION);
return makeSelect(className, methodName);
}
case OUTER:
case OUTER_COMPANION:
return makeQuotedQualIdent(qualifier, methodName);
case STATIC:
{
// top level method or class
// return makeSelect(gen().makeStaticQualifier(param.getDeclaration().getRefinedDeclaration()), methodName);
Declaration container = param.getDeclaration().getRefinedDeclaration();
if (!container.isToplevel() && !container.isStatic()) {
container = (Declaration) container.getContainer();
} else if (container.isStatic() && container instanceof TypedDeclaration) {
container = (Declaration) container.getContainer();
}
if (container instanceof TypedDeclaration) {
return makeSelect(makeName((TypedDeclaration) container, NA_FQ | NA_WRAPPER), methodName);
} else {
return makeSelect(gen().makeJavaType(((TypeDeclaration) container).getType(), AbstractTransformer.JT_RAW | AbstractTransformer.JT_NO_PRIMITIVES), methodName);
}
}
default:
// inner or local class or method, or method in an interface
return makeQuotedQualIdent(qualifier, methodName);
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class Naming method addNamesForWrapperClass.
private <R> void addNamesForWrapperClass(TypeDeclarationBuilder<R> builder, TypedDeclaration decl, int namingOptions) {
if ((namingOptions & NA_FQ) != 0) {
if ((namingOptions & NA_WRAPPER) == 0 && (namingOptions & NA_WRAPPER_UNQUOTED) == 0) {
throw new BugException("If you pass FQ you must pass WRAPPER or WRAPPER_UNQUOTED too, or there's no class name to qualify!");
}
List<String> outerNames = null;
Scope s = decl.getContainer();
boolean isInterop = false;
while (s != null) {
if (s instanceof Package) {
final List<String> packageName = isInterop ? ORG_ECLIPSE_CEYLON_LANGUAGE_PACKAGE : ((Package) s).getName();
for (int ii = 0; ii < packageName.size(); ii++) {
if (ii == 0 && packageName.get(ii).isEmpty()) {
continue;
}
builder.select(quoteIfJavaKeyword(packageName.get(ii)));
}
break;
} else if (s instanceof ClassOrInterface) {
ClassOrInterface c = (ClassOrInterface) s;
if (isJavaInterop(c))
isInterop = true;
if (outerNames == null) {
outerNames = new ArrayList<String>(2);
}
outerNames.add(getQuotedClassName(c, 0));
} else if (s instanceof TypedDeclaration) {
if (outerNames == null) {
outerNames = new ArrayList<String>(2);
}
outerNames.add(quoteIfJavaKeyword(getRealName((TypedDeclaration) s, 0)));
}
s = s.getContainer();
}
if (outerNames != null) {
for (int ii = outerNames.size() - 1; ii >= 0; ii--) {
String outerName = outerNames.get(ii);
builder.select(outerName);
}
}
}
if ((namingOptions & NA_WRAPPER) != 0) {
builder.select(getQuotedClassName(decl, namingOptions & (NA_GETTER | NA_SETTER)));
} else if ((namingOptions & NA_WRAPPER_UNQUOTED) != 0) {
builder.select(getRealName(decl, namingOptions & (NA_GETTER | NA_SETTER | NA_WRAPPER_UNQUOTED)));
} else if ((namingOptions & NA_Q_LOCAL_INSTANCE) != 0) {
if (Decl.isBoxedVariable(decl)) {
builder.select(getVariableBoxName(decl));
} else {
builder.select(getAttrClassName(decl, namingOptions & (NA_GETTER | NA_SETTER)));
}
}
if ((namingOptions & NA_WRAPPER_WITH_THIS) != 0) {
builder.select("this");
}
}
Aggregations