use of org.eclipse.ceylon.model.loader.model.OutputElement in project ceylon by eclipse.
the class AnnotationUtil method outputs.
public static EnumSet<OutputElement> outputs(Tree.AttributeDeclaration that) {
EnumSet<OutputElement> result = EnumSet.noneOf(OutputElement.class);
Value declarationModel = that.getDeclarationModel();
if (declarationModel != null) {
if (declarationModel.isClassMember()) {
if (declarationModel.isParameter()) {
result.add(PARAMETER);
}
if (ModelUtil.isCaptured(declarationModel)) {
result.add(GETTER);
if (!(that.getSpecifierOrInitializerExpression() instanceof Tree.LazySpecifierExpression)) {
result.add(FIELD);
}
} else if (!declarationModel.isParameter()) {
result.add(LOCAL_VARIABLE);
}
} else if (declarationModel.isInterfaceMember()) {
result.add(GETTER);
} else if (declarationModel.isToplevel()) {
result.add(GETTER);
// only non-lazy get fields
if (!declarationModel.isTransient())
result.add(FIELD);
} else {
if (declarationModel.isParameter()) {
result.add(PARAMETER);
} else {
result.add(LOCAL_VARIABLE);
}
}
}
if (result.contains(GETTER) && // variables with lazy value MUST have a distinct setter
((declarationModel.isVariable() && !declarationModel.isTransient()) || declarationModel.isLate())) {
result.add(SETTER);
}
return result;
}
use of org.eclipse.ceylon.model.loader.model.OutputElement in project ceylon by eclipse.
the class ExpressionTransformer method transform.
private List<JCAnnotation> transform(Object useSite, OutputElement target, Tree.AnnotationList annotationList, EnumSet<OutputElement> outputs) {
if (annotationList == null) {
return List.nil();
}
if ((gen().disableAnnotations & CeylonTransformer.DISABLE_USER_ANNOS) != 0) {
return List.nil();
}
LinkedHashMap<Class, ListBuffer<JCAnnotation>> annotationSet = new LinkedHashMap<>();
if (annotationList != null) {
if (annotationList.getAnonymousAnnotation() != null && AnnotationUtil.isNaturalTarget((Function) typeFact().getLanguageModuleDeclaration("doc"), useSite, target)) {
transformAnonymousAnnotation(annotationList.getAnonymousAnnotation(), annotationSet);
}
if (annotationList.getAnnotations() != null) {
for (Tree.Annotation annotation : annotationList.getAnnotations()) {
Function annoCtorDecl = ((Function) ((Tree.BaseMemberExpression) annotation.getPrimary()).getDeclaration());
if (annoCtorDecl != null) {
String aname = annoCtorDecl.getQualifiedNameString();
if ("java.lang::transient".equals(aname) || "java.lang::volatile".equals(aname) || "java.lang::synchronized".equals(aname) || "java.lang::native".equals(aname) || "java.lang::strictfp".equals(aname) || "java.lang::overloaded".equals(aname) || "java.lang::nonbean".equals(aname)) {
continue;
}
}
boolean isNaturalTarget = AnnotationUtil.isNaturalTarget(annoCtorDecl, useSite, target);
EnumSet<OutputElement> possibleTargets = AnnotationUtil.interopAnnotationTargeting(useSite instanceof Declaration ? isEe((Declaration) useSite) : false, outputs, annotation, false, false, useSite instanceof Declaration ? (Declaration) useSite : null);
if ((isNaturalTarget && possibleTargets == null) || (possibleTargets != null && possibleTargets.equals(EnumSet.of(target)))) {
transformAnnotation(annotation, annotationSet);
}
}
}
}
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
for (Class annotationClass : annotationSet.keySet()) {
ListBuffer<JCAnnotation> annotations = annotationSet.get(annotationClass);
if (isSequencedAnnotation(annotationClass)) {
JCAnnotation wrapperAnnotation = make().Annotation(makeJavaType(annotationClass.getType(), JT_ANNOTATIONS), List.<JCExpression>of(make().NewArray(null, null, upcastExprList(annotations.toList()))));
result.append(wrapperAnnotation);
} else if (isRepeatableAnnotation(annotationClass)) {
Interface containerAnnotation = getRepeatableContainer(annotationClass);
JCAnnotation wrapperAnnotation = make().Annotation(makeJavaType(containerAnnotation.appliedType(null, Collections.<Type>emptyList())), List.<JCExpression>of(make().NewArray(null, null, upcastExprList(annotations.toList()))));
result.append(wrapperAnnotation);
} else {
if (annotations.size() > 1) {
makeErroneous(annotationList, "compiler bug: multiple occurances of non-sequenced annotation class " + annotationClass.getQualifiedNameString());
}
result.appendList(annotations);
}
}
// Special case: Generate a @java.lang.Deprecated() if Ceylon deprecated
if (annotationList != null) {
for (Tree.Annotation annotation : annotationList.getAnnotations()) {
if (AnnotationUtil.isNaturalTarget((Function) typeFact().getLanguageModuleDeclaration("deprecated"), useSite, target) && isDeprecatedAnnotation(annotation.getPrimary()) && !(useSite instanceof Function) && !(useSite instanceof Constructor)) {
result.appendList(makeAtDeprecated());
}
}
}
return result.toList();
}
use of org.eclipse.ceylon.model.loader.model.OutputElement in project ceylon by eclipse.
the class UnsupportedVisitor method interopAnnotationTargeting.
private void interopAnnotationTargeting(EnumSet<OutputElement> outputs, Tree.AnnotationList annotationList, Tree.Declaration annotated) {
OutputElement target = null;
// let's do them as they come. See https://github.com/ceylon/ceylon/issues/5751
if (annotated instanceof Tree.AttributeDeclaration) {
if (((Tree.AttributeDeclaration) annotated).getSpecifierOrInitializerExpression() instanceof Tree.LazySpecifierExpression)
target = OutputElement.METHOD;
else
target = OutputElement.FIELD;
}
Declaration useSite = annotated.getDeclarationModel();
List<Annotation> annotations = annotationList.getAnnotations();
for (Tree.Annotation annotation : annotations) {
Function annoCtorDecl = ((Function) ((Tree.BaseMemberExpression) annotation.getPrimary()).getDeclaration());
boolean addWarnings = true;
// only add warnings if we don't have a natural target to pick from
if (target != null) {
addWarnings = !AnnotationUtil.isNaturalTarget(annoCtorDecl, useSite, target);
}
AnnotationUtil.interopAnnotationTargeting(eeVisitor.isEeMode(useSite), outputs, annotation, true, addWarnings, annotated.getDeclarationModel());
}
AnnotationUtil.duplicateInteropAnnotation(eeVisitor.isEeMode(useSite), outputs, annotations, annotated.getDeclarationModel());
}
use of org.eclipse.ceylon.model.loader.model.OutputElement 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.OutputElement in project ceylon by eclipse.
the class AnnotationUtil method duplicateInteropAnnotation.
public static void duplicateInteropAnnotation(boolean isEe, EnumSet<OutputElement> outputs, List<Annotation> annotations, Declaration d) {
for (int i = 0; i < annotations.size(); i++) {
Tree.Annotation ann = annotations.get(i);
Type t = ann.getTypeModel();
EnumSet<OutputElement> mainTargets = interopAnnotationTargeting(isEe, outputs, ann, false, false, d);
if (t != null && mainTargets != null) {
TypeDeclaration td = t.getDeclaration();
if (!ModelUtil.isCeylonDeclaration(td)) {
for (int j = 0; j < i; j++) {
Tree.Annotation other = annotations.get(j);
Type ot = other.getTypeModel();
if (ot != null) {
TypeDeclaration otd = ot.getDeclaration();
if (otd.equals(td)) {
// check if they have the same targets (if not that's fine)
EnumSet<OutputElement> dupeTargets = interopAnnotationTargeting(isEe, outputs, other, false, false, d);
if (dupeTargets != null) {
EnumSet<OutputElement> sameTargets = intersection(mainTargets, dupeTargets);
if (!sameTargets.isEmpty()) {
ann.addError("duplicate annotation: there are multiple annotations of type '" + td.getName() + "' for targets: '" + sameTargets + "'");
break;
}
}
}
}
}
}
}
}
}
Aggregations