use of org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod 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.loader.model.AnnotationProxyMethod in project ceylon by eclipse.
the class AbstractModelLoader method makeInteropAnnotationConstructor.
public AnnotationProxyMethod makeInteropAnnotationConstructor(LazyInterface iface, AnnotationProxyClass klass, OutputElement oe, Scope scope) {
String ctorName = oe == null ? NamingBase.getJavaBeanName(iface.getName()) : NamingBase.getDisambigAnnoCtorName(iface, oe);
AnnotationProxyMethod ctor = new AnnotationProxyMethod(this, klass, oe);
ctor.setAnnotationTarget(oe);
ctor.setContainer(scope);
ctor.setScope(scope);
if (!(scope instanceof Package)) {
ctor.setStatic(true);
}
ctor.setAnnotation(true);
ctor.setName(ctorName);
ctor.setShared(iface.isShared());
Annotation annotationAnnotation2 = new Annotation();
annotationAnnotation2.setName("annotation");
ctor.getAnnotations().add(annotationAnnotation2);
ctor.setType(((TypeDeclaration) iface).getType());
ctor.setUnit(iface.getUnit());
return ctor;
}
use of org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon by eclipse.
the class AbstractModelLoader method makeInteropAnnotation.
/**
* Creates extra members to be added to the {@code container} for annotation interop.
* For a Java declaration {@code @interface Annotation} we generate
* a model corresponding to:
* <pre>
* annotation class Annotation$Proxy(...) satisfies Annotation {
* // a `shared` class parameter for each method of Annotation
* }
* annotation JavaAnnotation javaAnnotation(...) => JavaAnnotation$Proxy(...);
* </pre>
*
* We also make a {@code *__method}, {@code *__field} etc version for each
* {@code @Target} program element
* @param iface The model of the annotation @interface
* @param container The container in which the generated members belong
* @return A list of members to add to the container
*/
public List<Declaration> makeInteropAnnotation(LazyInterface iface, Scope container) {
List<Declaration> declarations = new ArrayList<>();
AnnotationProxyClass klass = makeInteropAnnotationClass(iface, container);
AnnotationProxyMethod method = makeInteropAnnotationConstructor(iface, klass, null, container);
declarations.add(method);
for (OutputElement target : AnnotationTarget.outputTargets(klass)) {
declarations.add(makeInteropAnnotationConstructor(iface, klass, target, container));
}
declarations.add(klass);
return declarations;
}
use of org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon by eclipse.
the class AnnotationUtil method interopAnnotationTargeting.
/**
* Returns the set of output program elements that the given annotation
* could be applied to. If the {@code errors} flag is true then add
* warnings/errors to the tree about ambiguous/impossible targets.
*/
public static EnumSet<OutputElement> interopAnnotationTargeting(boolean isEe, EnumSet<OutputElement> outputs, Tree.Annotation annotation, boolean errors, boolean warnings, Declaration d) {
Declaration annoCtor = ((Tree.BaseMemberExpression) annotation.getPrimary()).getDeclaration();
if (annoCtor instanceof AnnotationProxyMethod) {
AnnotationProxyMethod proxyCtor = (AnnotationProxyMethod) annoCtor;
AnnotationProxyClass annoClass = proxyCtor.getProxyClass();
EnumSet<OutputElement> possibleTargets;
if (proxyCtor.getAnnotationTarget() != null) {
possibleTargets = EnumSet.of(proxyCtor.getAnnotationTarget());
} else {
possibleTargets = AnnotationTarget.outputTargets(annoClass);
}
EnumSet<OutputElement> actualTargets = possibleTargets.clone();
actualTargets.retainAll(outputs);
if (actualTargets.size() > 1) {
if (warnings) {
StringBuffer sb = new StringBuffer();
sb.append("ambiguous annotation target: ").append(annoCtor.getName());
sb.append(" could be applied to several targets, use one of ");
for (Iterator<OutputElement> iterator = actualTargets.iterator(); iterator.hasNext(); ) {
OutputElement x = iterator.next();
sb.append(Naming.getDisambigAnnoCtorName((Interface) ((AnnotationProxyMethod) annoCtor).getProxyClass().iface, x));
if (iterator.hasNext()) {
sb.append(", ");
}
}
sb.append(" to disambiguate");
annotation.addUsageWarning(Warning.ambiguousAnnotation, sb.toString(), Backend.Java);
}
checkForLateFieldAnnotation(isEe, annotation, d, annoCtor, possibleTargets, actualTargets);
return null;
} else if (actualTargets.size() == 0) {
if (errors) {
annotation.addError("no target for " + annoCtor.getName() + " annotation: @Target of @interface " + ((AnnotationProxyClass) annoClass).iface.getName() + " lists " + possibleTargets + " but annotated element tranforms to " + outputs, Backend.Java);
}
}
checkForLateFieldAnnotation(isEe, annotation, d, annoCtor, possibleTargets, actualTargets);
return actualTargets;
} else {
return null;
}
}
Aggregations