use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class BoxingDeclarationVisitor method setBoxingState.
private void setBoxingState(TypedDeclaration declaration, TypedDeclaration refinedDeclaration, Node that) {
Type type = declaration.getType();
if (type == null) {
// an error must have already been reported
return;
}
// fetch the real refined declaration if required
if (Decl.equal(declaration, refinedDeclaration) && declaration instanceof FunctionOrValue && ((FunctionOrValue) declaration).isParameter() && declaration.getContainer() instanceof Class) {
// maybe it is really inherited from a field?
FunctionOrValue methodOrValueForParam = (FunctionOrValue) declaration;
if (methodOrValueForParam != null) {
// make sure we get the refined version of that member
refinedDeclaration = (TypedDeclaration) methodOrValueForParam.getRefinedDeclaration();
}
}
// inherit underlying type constraints
if (!Decl.equal(refinedDeclaration, declaration)) {
// simple case
if (type.getUnderlyingType() == null && refinedDeclaration.getType() != null) {
if (type.isCached()) {
type = type.clone();
}
type.setUnderlyingType(refinedDeclaration.getType().getUnderlyingType());
declaration.setType(type);
}
// special case for variadics
if (Decl.isValueParameter(refinedDeclaration)) {
Parameter parameter = ((FunctionOrValue) refinedDeclaration).getInitializerParameter();
if (parameter.isSequenced()) {
// inherit the underlying type of the iterated type
Type refinedIteratedType = refinedDeclaration.getType().getTypeArgumentList().get(0);
if (refinedIteratedType.getUnderlyingType() != null) {
Type ourIteratedType = type.getTypeArgumentList().get(0);
if (ourIteratedType.getUnderlyingType() == null) {
if (ourIteratedType.isCached()) {
ourIteratedType = ourIteratedType.clone();
}
ourIteratedType.setUnderlyingType(refinedIteratedType.getUnderlyingType());
type.getTypeArgumentList().set(0, ourIteratedType);
// make sure we remove those types from the cache otherwise UGLY things happen
TypeCache cache = type.getDeclaration().getUnit().getCache();
if (cache != null) {
cache.remove(ourIteratedType);
cache.remove(type);
}
}
}
}
}
}
// abort if our boxing state has already been set
if (declaration.getUnboxed() != null)
return;
// functional parameter return values are always boxed if we're not creating a method for them
if (declaration instanceof Function && ((Function) declaration).isParameter() && !JvmBackendUtil.createMethod((Function) declaration)) {
declaration.setUnboxed(false);
return;
}
if (!Decl.equal(refinedDeclaration, declaration)) {
// make sure refined declarations have already been set
if (refinedDeclaration.getUnboxed() == null)
setBoxingState(refinedDeclaration, refinedDeclaration, that);
// inherit
declaration.setUnboxed(refinedDeclaration.getUnboxed());
} else if (declaration instanceof Function && Strategy.useBoxedVoid((Function) declaration) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
declaration.setUnboxed(false);
} else if ((isCeylonBasicType(type) || Decl.isUnboxedVoid(declaration)) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && (refinedDeclaration.getContainer() instanceof Declaration == false || !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration)) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
boolean unbox = !forceBoxedLocals || !(declaration instanceof Value) || !Decl.isLocal(declaration) || Decl.isParameter(declaration) || Decl.isTransient(declaration);
// until it's used later by user code
if (declaration.getOriginalDeclaration() != null && declaration.hasUncheckedNullType())
unbox = false;
declaration.setUnboxed(unbox);
} else if (Decl.isValueParameter(declaration) && CodegenUtil.isContainerFunctionalParameter(declaration) && JvmBackendUtil.createMethod((FunctionOrValue) declaration.getContainer())) {
Function functionalParameter = (Function) declaration.getContainer();
TypedDeclaration refinedFrom = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(functionalParameter, optimisedMethodSpecifiersToMethods);
if (Decl.equal(refinedFrom, functionalParameter)) {
// not a method return type (where void would be considered unboxed).
if (declaration.getUnit().getAnythingType().isExactly(declaration.getType()) || declaration.getUnit().isOptionalType(declaration.getType())) {
declaration.setUnboxed(false);
} else {
declaration.setUnboxed(true);
}
} else {
// make sure refined declarations have already been set
if (refinedFrom.getUnboxed() == null)
setBoxingState(refinedFrom, refinedFrom, that);
// inherit
declaration.setUnboxed(refinedFrom.getUnboxed());
}
} else {
declaration.setUnboxed(false);
}
// Any "@boxed" or "@unboxed" compiler annotation overrides
boxFromAnnotation(declaration, that);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class BoxingDeclarationVisitor method setErasureState.
private void setErasureState(TypedDeclaration decl) {
// deal with invalid input
if (decl == null)
return;
Type type = decl.getType();
boolean erased = false;
boolean untrusted = false;
if (type != null) {
if (hasErasure(type) || hasSubstitutedBounds(type) || type.isTypeConstructor()) {
erased = true;
}
if (decl.isActual() && decl.getContainer() instanceof ClassOrInterface) {
TypedDeclaration refinedDeclaration = getRefinedDeclarationForWideningRules(decl);
if (refinedDeclaration != null && refinedDeclaration != decl && decl.getUntrustedType() == null) {
// make sure the refined decl is set before we look at it
setErasureState(refinedDeclaration);
}
// make sure we did not lose type information due to non-widening
if (isWideningTypedDeclaration(decl)) {
// widening means not trusting the type, otherwise we end up thinking that the type is
// something it's not and regular erasure rules don't apply there
untrusted = true;
erased = true;
}
}
}
decl.setTypeErased(erased);
if (isPinnedType(decl)) {
untrusted = true;
}
decl.setUntrustedType(untrusted);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class BoxingDeclarationVisitor method visit.
@Override
public void visit(AttributeSetterDefinition that) {
super.visit(that);
Setter declaration = that.getDeclarationModel();
// deal with invalid input
if (declaration == null)
return;
// To determine boxing for a setter we use its parameter
TypedDeclaration paramDeclaration = declaration.getParameter().getModel();
boxAttribute(paramDeclaration, that);
// Now copy the settings from the parameter to the setter itself
declaration.setUnboxed(paramDeclaration.getUnboxed());
// Then we check if there are any overriding compiler annotations
boxFromAnnotation(declaration, that);
// And finally we copy the setting back again to make sure they're really the same
paramDeclaration.setUnboxed(declaration.getUnboxed());
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class BoxingDeclarationVisitor method visit.
@Override
public void visit(Variable that) {
super.visit(that);
TypedDeclaration declaration = that.getDeclarationModel();
// deal with invalid input
if (declaration == null)
return;
setBoxingState(declaration, declaration, that);
rawTypedDeclaration(declaration);
setErasureState(declaration);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class BoxingVisitor method visit.
@Override
public void visit(IndexExpression that) {
super.visit(that);
// we need to propagate from the underlying method call (item/span)
if (that.getPrimary() == null || that.getPrimary().getTypeModel() == null)
return;
Type lhsModel = that.getPrimary().getTypeModel();
if (lhsModel.getDeclaration() == null)
return;
String methodName = that.getElementOrRange() instanceof Tree.Element ? "get" : "span";
// find the method from its declaration
TypedDeclaration member = (TypedDeclaration) lhsModel.getDeclaration().getMember(methodName, null, false);
if (member == null)
return;
propagateFromDeclaration(that, member);
// also copy the underlying type, mostly useful for java primitive arrays
if (member.getType().getUnderlyingType() != null) {
Type type = that.getTypeModel();
if (type.isCached())
type = type.clone();
type.setUnderlyingType(member.getType().getUnderlyingType());
that.setTypeModel(type);
}
}
Aggregations