use of com.redhat.ceylon.model.loader.model.OutputElement in project ceylon-compiler by ceylon.
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 && 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());
EnumSet<OutputElement> possibleTargets = AnnotationUtil.interopAnnotationTargeting(outputs, annotation, false);
if ((isNaturalTarget(annoCtorDecl, useSite, target) && possibleTargets == null) || (possibleTargets != null && possibleTargets.equals(EnumSet.of(target)))) {
transformAnnotation(annotation, annotationSet);
}
}
}
}
ListBuffer<JCAnnotation> result = ListBuffer.lb();
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, (List) 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 (isNaturalTarget((Function) typeFact().getLanguageModuleDeclaration("deprecated"), useSite, target) && isDeprecatedAnnotation(annotation.getPrimary())) {
result.append(make().Annotation(make().Type(syms().deprecatedType), List.<JCExpression>nil()));
}
}
}
return result.toList();
}
use of com.redhat.ceylon.model.loader.model.OutputElement in project ceylon-compiler by ceylon.
the class AnnotationUtil method duplicateInteropAnnotation.
public static void duplicateInteropAnnotation(EnumSet<OutputElement> outputs, List<Annotation> annotations) {
for (int i = 0; i < annotations.size(); i++) {
Tree.Annotation ann = annotations.get(i);
Type t = ann.getTypeModel();
EnumSet<OutputElement> mainTargets = interopAnnotationTargeting(outputs, ann, false);
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(outputs, other, false);
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;
}
}
}
}
}
}
}
}
}
use of com.redhat.ceylon.model.loader.model.OutputElement in project ceylon-compiler by ceylon.
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 (declarationModel.isShared() || declarationModel.isCaptured()) {
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);
result.add(FIELD);
} else {
if (declarationModel.isParameter()) {
result.add(PARAMETER);
} else {
result.add(LOCAL_VARIABLE);
}
}
}
if (result.contains(GETTER) && (declarationModel.isVariable() || declarationModel.isLate())) {
result.add(SETTER);
}
return result;
}
use of com.redhat.ceylon.model.loader.model.OutputElement in project ceylon-compiler by ceylon.
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 ambigous/impossible targets.
*/
public static EnumSet<OutputElement> interopAnnotationTargeting(EnumSet<OutputElement> outputs, Tree.Annotation annotation, boolean errors) {
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 (errors) {
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);
}
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);
}
}
return actualTargets;
} else {
return null;
}
}
Aggregations