use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class AnnotationModelVisitor method visit.
@Override
public void visit(Tree.BaseMemberExpression bme) {
if (annotationConstructor != null) {
Declaration declaration = bme.getDeclaration();
if (checkingInvocationPrimary && isAnnotationConstructor(bme.getDeclaration())) {
Function ctor = (Function) bme.getDeclaration();
instantiation.setPrimary(ctor);
if (ctor.getAnnotationConstructor() != null && ctor.getAnnotationConstructor() != instantiation) {
for (AnnotationConstructorParameter p : ((AnnotationInvocation) ctor.getAnnotationConstructor()).getConstructorParameters()) {
instantiation.addConstructorParameter(p);
}
}
} else if (checkingArguments || checkingDefaults) {
if (declaration instanceof Value && ((Value) declaration).isParameter()) {
Value constructorParameter = (Value) declaration;
ParameterAnnotationTerm a = new ParameterAnnotationTerm();
a.setSpread(spread);
// XXX Is this right?
a.setSourceParameter(constructorParameter.getInitializerParameter());
this.term = a;
} else if (isBooleanTrue(declaration)) {
LiteralAnnotationTerm argument = new BooleanLiteralAnnotationTerm(true);
appendLiteralArgument(bme, argument);
} else if (isBooleanFalse(declaration)) {
LiteralAnnotationTerm argument = new BooleanLiteralAnnotationTerm(false);
appendLiteralArgument(bme, argument);
} else if (bme.getUnit().isEmptyType(bme.getTypeModel()) && bme.getUnit().isIterableType(bme.getTypeModel()) && elements == null) {
// If we're dealing with an iterable, empty means empty collection, not object
endCollection(startCollection(bme), bme);
} else if (Decl.isAnonCaseOfEnumeratedType(bme)) {
LiteralAnnotationTerm argument = new ObjectLiteralAnnotationTerm(bme.getTypeModel());
appendLiteralArgument(bme, argument);
} else {
bme.addError("compiler bug: unsupported base member expression in annotation constructor", Backend.Java);
}
} else {
bme.addError("compiler bug: unsupported base member expression in annotation constructor", Backend.Java);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class AnnotationUtil method isNaturalTarget.
/**
* Whether an annotation (with the given {@code annotationCtorDecl}
* annotation constructor) used on the given declaration ({@code useSite})
* should be added to the Java annotations of the given generated program
* elements ({@code target})
* @param annotationCtorDecl
* @param useSite
* @param target
* @return
*/
public static boolean isNaturalTarget(// use site is either a Declaration, or a Package, or a Module,
Function annotationCtorDecl, // module imports
Object useSite, OutputElement target) {
EnumSet<AnnotationTarget> interopTargets;
if (annotationCtorDecl instanceof AnnotationProxyMethod) {
AnnotationProxyMethod annotationProxyMethod = (AnnotationProxyMethod) annotationCtorDecl;
if (annotationProxyMethod.getAnnotationTarget() == target) {
// Foo__WHATEVER, so honour the WHATEVER
return true;
}
interopTargets = annotationProxyMethod.getAnnotationTargets();
} else {
interopTargets = null;
}
if (useSite instanceof Declaration) {
if (ModelUtil.isConstructor((Declaration) useSite)) {
if (useSite instanceof Functional) {
return target == OutputElement.CONSTRUCTOR;
} else if (useSite instanceof Value) {
// If the constructor has a getter we can't annotate, let's
// put the annotations on the constructor
Class constructedClass = ModelUtil.getConstructedClass((Declaration) useSite);
// See CeylonVisitor.transformSingletonConstructor for those tests
if (constructedClass.isToplevel() || constructedClass.isClassMember())
return target == OutputElement.GETTER;
return target == OutputElement.CONSTRUCTOR;
}
} else if (useSite instanceof Class) {
if (((Class) useSite).getParameterList() != null && interopTargets != null && interopTargets.contains(AnnotationTarget.CONSTRUCTOR) && !interopTargets.contains(AnnotationTarget.TYPE)) {
return target == OutputElement.CONSTRUCTOR;
}
return target == OutputElement.TYPE;
} else if (useSite instanceof Interface) {
return target == OutputElement.TYPE;
} else if (useSite instanceof Value) {
Value value = (Value) useSite;
boolean p = value.isParameter() && target == OutputElement.PARAMETER;
if (annotationCtorDecl instanceof AnnotationProxyMethod) {
if (!value.isTransient() && (interopTargets == null || interopTargets.contains(AnnotationTarget.FIELD))) {
return target == OutputElement.FIELD;
} else {
return target == OutputElement.GETTER;
}
} else {
return p || target == OutputElement.GETTER;
}
} else if (useSite instanceof Setter) {
return target == OutputElement.SETTER;
} else if (useSite instanceof Function) {
return target == OutputElement.METHOD;
} else if (useSite instanceof Constructor) {
return target == OutputElement.CONSTRUCTOR;
} else if (useSite instanceof TypeAlias) {
return target == OutputElement.TYPE;
}
} else if (useSite instanceof Package) {
return (annotationCtorDecl instanceof AnnotationProxyMethod) ? target == OutputElement.PACKAGE : target == OutputElement.TYPE;
} else if (useSite instanceof Module) {
return target == OutputElement.TYPE;
} else if (useSite instanceof Tree.ImportModule) {
return target == OutputElement.FIELD;
}
throw new RuntimeException("" + useSite);
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class ExpressionVisitor method accountForIntermediateRefinements.
private Reference accountForIntermediateRefinements(Tree.SpecifierStatement that, FunctionOrValue refinedMethodOrValue, FunctionOrValue methodOrValue, ClassOrInterface refiningType, List<Declaration> interveningRefinements) {
// accumulate an intersection of the types of
// everything it refines
List<Type> refinedTypes = new ArrayList<Type>();
// don't check this one here because it is
// separately checked in visit(SpecifierStatement)
Reference refinedProducedReference = getRefinedMemberReference(refinedMethodOrValue, refiningType);
Map<TypeParameter, Type> substs = substitutions(refinedMethodOrValue, methodOrValue);
Type refinedType = refinedProducedReference.getType().substitute(substs, null);
boolean allHaveNulls = hasNullReturnValues(refinedType, refinedMethodOrValue);
intersectReturnType(refinedTypes, refinedType);
for (Declaration intervening : interveningRefinements) {
if (intervening instanceof FunctionOrValue && // factors here as well?
!refinedMethodOrValue.equals(intervening)) {
FunctionOrValue refinement = (FunctionOrValue) intervening;
Reference refinedMember = getRefinedMemberReference(refinement, refiningType);
Map<TypeParameter, Type> subs = substitutions(refinement, methodOrValue);
Type type = refinedMember.getType().substitute(subs, null);
allHaveNulls = allHaveNulls && hasNullReturnValues(type, refinement);
intersectReturnType(refinedTypes, type);
checkIntermediateRefinement(that, refinement, refinedMember);
}
}
Type it = canonicalIntersection(refinedTypes, unit);
if (allHaveNulls && !unit.isOptionalType(it)) {
methodOrValue.setUncheckedNullType(true);
Tree.Term lhs = that.getBaseMemberExpression();
// TODO: this is pretty ugly, think of something better!
lhs.setTypeModel(unit.getOptionalType(lhs.getTypeModel()));
}
methodOrValue.setType(it);
return refinedProducedReference;
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class ExpressionVisitor method beginReturnDeclaration.
private Declaration beginReturnDeclaration(Declaration d) {
Declaration od = returnDeclaration;
returnDeclaration = d;
return od;
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class ExpressionVisitor method checkReferenceIsNonVariable.
private void checkReferenceIsNonVariable(Tree.BaseMemberExpression ref, boolean isSwitch) {
Declaration d = ref.getDeclaration();
if (d != null) {
int code = isSwitch ? 3101 : 3100;
String help = " (assign to a new local value to narrow type)";
if (!(d instanceof Value)) {
ref.addError("referenced declaration is not a value: '" + d.getName(unit) + "'", code);
} else if (isNonConstant(d)) {
ref.addError("referenced value is non-constant: '" + d.getName(unit) + "'" + help, code);
} else if (d.isDefault() || d.isFormal()) {
ref.addError("referenced value may be refined by a non-constant value: '" + d.getName(unit) + "'" + help, code);
}
}
}
Aggregations