Skip to content

Commit

Permalink
Converts AnnotationRewriter to new type system.
Browse files Browse the repository at this point in the history
	Change on 2016/11/03 by kstanger <kstanger@google.com>

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=138087457
  • Loading branch information
kstanger authored and tomball committed Nov 4, 2016
1 parent 48dc5b6 commit ceff814
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 107 deletions.
Expand Up @@ -30,7 +30,7 @@ public AnnotationTypeMemberDeclaration() {}

public AnnotationTypeMemberDeclaration(AnnotationTypeMemberDeclaration other) {
super(other);
element = other.getElement();
element = other.getExecutableElement();
type.copyFrom(other.getType());
name.copyFrom(other.getName());
defaultValue.copyFrom(other.getDefault());
Expand All @@ -41,22 +41,42 @@ public Kind getKind() {
return Kind.ANNOTATION_TYPE_MEMBER_DECLARATION;
}

public ExecutableElement getElement() {
public ExecutableElement getExecutableElement() {
return element;
}

public AnnotationTypeMemberDeclaration setExecutableElement(ExecutableElement newElement) {
element = newElement;
return this;
}

public Type getType() {
return type.get();
}

public AnnotationTypeMemberDeclaration setType(Type newType) {
type.set(newType);
return this;
}

public SimpleName getName() {
return name.get();
}

public AnnotationTypeMemberDeclaration setName(SimpleName newName) {
name.set(newName);
return this;
}

public Expression getDefault() {
return defaultValue.get();
}

public AnnotationTypeMemberDeclaration setDefault(Expression newDefault) {
defaultValue.set(newDefault);
return this;
}

@Override
protected void acceptInner(TreeVisitor visitor) {
if (visitor.visit(this)) {
Expand All @@ -73,24 +93,4 @@ protected void acceptInner(TreeVisitor visitor) {
public AnnotationTypeMemberDeclaration copy() {
return new AnnotationTypeMemberDeclaration(this);
}

public AnnotationTypeMemberDeclaration setDefault(Expression newDefault) {
defaultValue.set(newDefault);
return this;
}

public AnnotationTypeMemberDeclaration setElement(ExecutableElement newElement) {
element = newElement;
return this;
}

public AnnotationTypeMemberDeclaration setName(SimpleName newName) {
name.set(newName);
return this;
}

public AnnotationTypeMemberDeclaration setType(Type newType) {
type.set(newType);
return this;
}
}
Expand Up @@ -429,7 +429,7 @@ public static Expression newLiteral(Object value, Types typeEnv) {
} else if (value instanceof String) {
return new StringLiteral((String) value, typeEnv);
}
throw new AssertionError("unknown constant type");
throw new AssertionError("unknown constant type: " + value.getClass().getName());
}

/**
Expand Down
Expand Up @@ -32,9 +32,9 @@ public JdtAnnotationValue(Object value) {
this.value = BindingConverter.getType((ITypeBinding) value);
} else if (value instanceof IAnnotationBinding) {
this.value = new JdtAnnotationMirror((IAnnotationBinding) value);
} else if (value instanceof List) {
} else if (value instanceof Object[]) {
List<AnnotationValue> newValues = new ArrayList<AnnotationValue>();
for (Object o : ((List<?>) value)) {
for (Object o : ((Object[]) value)) {
newValues.add(new JdtAnnotationValue(o));
}
this.value = newValues;
Expand Down
Expand Up @@ -76,6 +76,7 @@ public List<? extends VariableElement> getParameters() {
return params;
}

@Override
public TypeMirror getReceiverType() {
throw new AssertionError("not implemented");
}
Expand All @@ -90,6 +91,7 @@ public boolean isVarArgs() {
return ((JdtMethodBinding) binding).isVarargs();
}

@Override
public boolean isDefault() {
throw new AssertionError("not implemented");
}
Expand All @@ -105,7 +107,8 @@ public List<? extends TypeMirror> getThrownTypes() {

@Override
public AnnotationValue getDefaultValue() {
return new JdtAnnotationValue(((JdtMethodBinding) binding).getDefaultValue());
Object value = ((JdtMethodBinding) binding).getDefaultValue();
return value == null ? null : new JdtAnnotationValue(value);
}

@Override
Expand Down
Expand Up @@ -121,7 +121,6 @@
import com.google.j2objc.annotations.Property;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import org.eclipse.jdt.core.dom.ASTNode;
Expand Down Expand Up @@ -402,7 +401,7 @@ private static TreeNode convertAnnotationTypeMemberDeclaration(
AnnotationTypeMemberDeclaration newNode = new AnnotationTypeMemberDeclaration();
convertBodyDeclaration(node, newNode);
return newNode
.setElement((ExecutableElement) BindingConverter.getElement(node.resolveBinding()))
.setExecutableElement(BindingConverter.getExecutableElement(node.resolveBinding()))
.setName((SimpleName) convert(node.getName()))
.setType((Type) convert(node.getType()))
.setDefault((Expression) convert(node.getDefault()));
Expand Down
Expand Up @@ -31,21 +31,21 @@
import com.google.devtools.j2objc.ast.TreeUtil;
import com.google.devtools.j2objc.ast.TypeLiteral;
import com.google.devtools.j2objc.ast.UnitTreeVisitor;
import com.google.devtools.j2objc.jdt.BindingConverter;
import com.google.devtools.j2objc.types.GeneratedExecutableElement;
import com.google.devtools.j2objc.types.GeneratedMethodBinding;
import com.google.devtools.j2objc.types.GeneratedVariableBinding;
import com.google.devtools.j2objc.util.BindingUtil;
import com.google.devtools.j2objc.types.GeneratedVariableElement;
import com.google.devtools.j2objc.util.ElementUtil;
import com.google.devtools.j2objc.util.NameTable;
import com.google.devtools.j2objc.util.TypeUtil;
import com.google.devtools.j2objc.util.UnicodeUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Modifier;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

/**
* Adds fields and properties to annotation types.
Expand All @@ -60,56 +60,52 @@ public AnnotationRewriter(CompilationUnit unit) {

@Override
public void endVisit(AnnotationTypeDeclaration node) {
ITypeBinding type = node.getTypeBinding();
if (!BindingUtil.isRuntimeAnnotation(type)) {
TypeElement type = node.getTypeElement();
if (!ElementUtil.isRuntimeAnnotation(type)) {
return;
}
List<AnnotationTypeMemberDeclaration> members = TreeUtil.getAnnotationMembers(node);
List<BodyDeclaration> bodyDecls = node.getBodyDeclarations();

Map<IMethodBinding, IVariableBinding> fieldBindings = createMemberFields(node, members);
addMemberProperties(node, members, fieldBindings);
Map<ExecutableElement, VariableElement> fieldElements = createMemberFields(node, members);
addMemberProperties(node, members, fieldElements);
addDefaultAccessors(node, members);
bodyDecls.add(createAnnotationTypeMethod(type));
bodyDecls.add(createDescriptionMethod(type));
addConstructor(node, fieldBindings);
addConstructor(node, fieldElements);
}

// Create an instance field for each member.
private Map<IMethodBinding, IVariableBinding> createMemberFields(
private Map<ExecutableElement, VariableElement> createMemberFields(
AnnotationTypeDeclaration node, List<AnnotationTypeMemberDeclaration> members) {
ITypeBinding type = node.getTypeBinding();
Map<IMethodBinding, IVariableBinding> fieldBindings = new HashMap<>();
TypeElement type = node.getTypeElement();
Map<ExecutableElement, VariableElement> fieldElements = new HashMap<>();
for (AnnotationTypeMemberDeclaration member : members) {
IMethodBinding memberBinding = (IMethodBinding)
BindingConverter.unwrapElement(member.getElement());
ITypeBinding memberType = memberBinding.getReturnType();
String propName = NameTable.getAnnotationPropertyName(memberBinding);
GeneratedVariableBinding field = new GeneratedVariableBinding(
propName, BindingUtil.ACC_SYNTHETIC, memberType, true, false, type, null);
ExecutableElement memberElement = member.getExecutableElement();
String propName = NameTable.getAnnotationPropertyName(memberElement);
VariableElement field = GeneratedVariableElement.newField(
propName, memberElement.getReturnType(), type);
node.addBodyDeclaration(new FieldDeclaration(field, null));
fieldBindings.put(memberBinding, field);
fieldElements.put(memberElement, field);
}
return fieldBindings;
return fieldElements;
}

// Generate the property declarations and synthesize statements.
private void addMemberProperties(
AnnotationTypeDeclaration node, List<AnnotationTypeMemberDeclaration> members,
Map<IMethodBinding, IVariableBinding> fieldBindings) {
Map<ExecutableElement, VariableElement> fieldElements) {
if (members.isEmpty()) {
return;
}
StringBuilder propertyDecls = new StringBuilder();
StringBuilder propertyImpls = new StringBuilder();
for (AnnotationTypeMemberDeclaration member : members) {
IMethodBinding memberBinding = (IMethodBinding)
BindingConverter.unwrapElement(member.getElement());
ITypeBinding memberType = memberBinding.getReturnType();
String propName = NameTable.getAnnotationPropertyName(memberBinding);
String memberTypeStr = nameTable.getObjCType(memberType);
ExecutableElement memberElement = member.getExecutableElement();
String propName = NameTable.getAnnotationPropertyName(memberElement);
String memberTypeStr = nameTable.getObjCType(memberElement.getReturnType());

String fieldName = nameTable.getVariableShortName(fieldBindings.get(memberBinding));
String fieldName = nameTable.getVariableShortName(fieldElements.get(memberElement));
propertyDecls.append(UnicodeUtils.format("@property (readonly) %s%s%s;\n",
memberTypeStr, memberTypeStr.endsWith("*") ? "" : " ", propName));
if (NameTable.needsObjcMethodFamilyNoneAttribute(propName)) {
Expand All @@ -125,20 +121,21 @@ private void addMemberProperties(
// Create accessors for properties that have default values.
private void addDefaultAccessors(
AnnotationTypeDeclaration node, List<AnnotationTypeMemberDeclaration> members) {
ITypeBinding type = node.getTypeBinding();
TypeElement type = node.getTypeElement();
for (AnnotationTypeMemberDeclaration member : members) {
IMethodBinding memberBinding = BindingConverter.unwrapExecutableElement(member.getElement());
Object defaultValue = memberBinding.getDefaultValue();
if (defaultValue == null) {
ExecutableElement memberElement = member.getExecutableElement();
AnnotationValue defaultValue = memberElement.getDefaultValue();
if (defaultValue == null || defaultValue.getValue() == null) {
continue;
}

ITypeBinding memberType = memberBinding.getReturnType();
String propName = NameTable.getAnnotationPropertyName(memberBinding);
TypeMirror memberType = memberElement.getReturnType();
String propName = NameTable.getAnnotationPropertyName(memberElement);

GeneratedMethodBinding defaultGetterBinding = GeneratedMethodBinding.newMethod(
propName + "Default", Modifier.STATIC | BindingUtil.ACC_SYNTHETIC, memberType, type);
MethodDeclaration defaultGetter = new MethodDeclaration(defaultGetterBinding);
ExecutableElement defaultGetterElement = GeneratedExecutableElement.newMethodWithSelector(
propName + "Default", memberType, type)
.addModifiers(Modifier.STATIC);
MethodDeclaration defaultGetter = new MethodDeclaration(defaultGetterElement);
defaultGetter.setHasDeclaration(false);
Block defaultGetterBody = new Block();
defaultGetter.setBody(defaultGetterBody);
Expand All @@ -149,54 +146,53 @@ private void addDefaultAccessors(
}

private void addConstructor(
AnnotationTypeDeclaration node, Map<IMethodBinding, IVariableBinding> fieldBindings) {
ITypeBinding type = node.getTypeBinding();
AnnotationTypeDeclaration node, Map<ExecutableElement, VariableElement> fieldElements) {
TypeElement type = node.getTypeElement();
String typeName = nameTable.getFullName(type);
FunctionDeclaration constructorDecl = new FunctionDeclaration("create_" + typeName, type, type);
FunctionDeclaration constructorDecl =
new FunctionDeclaration("create_" + typeName, type.asType(), type.asType());
Block constructorBody = new Block();
constructorDecl.setBody(constructorBody);
List<Statement> stmts = constructorBody.getStatements();

stmts.add(new NativeStatement(UnicodeUtils.format(
"%s *self = AUTORELEASE([[%s alloc] init]);", typeName, typeName)));

for (IMethodBinding memberBinding : BindingUtil.getSortedAnnotationMembers(type)) {
ITypeBinding memberType = memberBinding.getReturnType();
String propName = NameTable.getAnnotationPropertyName(memberBinding);
String fieldName = nameTable.getVariableShortName(fieldBindings.get(memberBinding));
for (ExecutableElement memberElement : ElementUtil.getSortedAnnotationMembers(type)) {
TypeMirror memberType = memberElement.getReturnType();
String propName = NameTable.getAnnotationPropertyName(memberElement);
String fieldName = nameTable.getVariableShortName(fieldElements.get(memberElement));

GeneratedVariableBinding param = new GeneratedVariableBinding(
propName, 0, memberType, false, true, null, null);
VariableElement param = GeneratedVariableElement.newParameter(propName, memberType, null);
constructorDecl.addParameter(new SingleVariableDeclaration(param));
String rhs = memberType.isPrimitive() ? propName : "RETAIN_(" + propName + ")";
String rhs = TypeUtil.isReferenceType(memberType) ? "RETAIN_(" + propName + ")" : propName;
stmts.add(new NativeStatement("self->" + fieldName + " = " + rhs + ";"));
}

stmts.add(new NativeStatement("return self;"));
node.addBodyDeclaration(constructorDecl);
}

private MethodDeclaration createAnnotationTypeMethod(ITypeBinding type) {
GeneratedMethodBinding annotationTypeBinding = GeneratedMethodBinding.newMethod(
"annotationType", BindingUtil.ACC_SYNTHETIC, typeEnv.getIOSClass(), type);
MethodDeclaration annotationTypeMethod = new MethodDeclaration(annotationTypeBinding);
private MethodDeclaration createAnnotationTypeMethod(TypeElement type) {
ExecutableElement annotationTypeElement = GeneratedExecutableElement.newMethodWithSelector(
"annotationType", typeEnv.resolveJavaTypeMirror("java.lang.Class"), type);
MethodDeclaration annotationTypeMethod = new MethodDeclaration(annotationTypeElement);
annotationTypeMethod.setHasDeclaration(false);
Block annotationTypeBody = new Block();
annotationTypeMethod.setBody(annotationTypeBody);
annotationTypeBody.addStatement(new ReturnStatement(new TypeLiteral(type, typeEnv)));
annotationTypeBody.addStatement(new ReturnStatement(new TypeLiteral(type.asType(), typeEnv)));
return annotationTypeMethod;
}

private MethodDeclaration createDescriptionMethod(ITypeBinding type) {
private MethodDeclaration createDescriptionMethod(TypeElement type) {
ExecutableElement descriptionElement = GeneratedExecutableElement.newMethodWithSelector(
"description", BindingConverter.getType(typeEnv.getNSString()),
BindingConverter.getTypeElement(type));
"description", typeEnv.resolveJavaTypeMirror("java.lang.String"), type);
MethodDeclaration descriptionMethod = new MethodDeclaration(descriptionElement);
descriptionMethod.setHasDeclaration(false);
Block descriptionBody = new Block();
descriptionMethod.setBody(descriptionBody);
descriptionBody.addStatement(new ReturnStatement(
new StringLiteral("@" + type.getBinaryName() + "()", typeEnv)));
new StringLiteral("@" + elementUtil.getBinaryName(type) + "()", typeEnv)));
return descriptionMethod;
}
}
Expand Up @@ -206,8 +206,8 @@ private int generateMethodsMetadata() {
// Add property accessor and static default methods.
for (AnnotationTypeMemberDeclaration decl : TreeUtil.getAnnotationMembers(typeNode)) {
String name = decl.getName().getIdentifier();
IMethodBinding memberBinding = (IMethodBinding)
BindingConverter.unwrapElement(decl.getElement());
IMethodBinding memberBinding =
BindingConverter.unwrapExecutableElement(decl.getExecutableElement());
String returnType = getTypeName(memberBinding.getReturnType());
String metadata = UnicodeUtils.format(" { NULL, %s, 0x%x, -1, -1, -1, -1, -1, -1 },\n",
cStr(returnType),
Expand Down
Expand Up @@ -647,23 +647,6 @@ public static boolean isRuntimeAnnotation(ITypeBinding binding) {
return false;
}

/**
* Returns an alphabetically sorted list of an annotation type's members.
* This is necessary since an annotation's values can be specified in any
* order, but the annotation's constructor needs to be invoked using its
* declaration order.
*/
public static IMethodBinding[] getSortedAnnotationMembers(ITypeBinding annotation) {
IMethodBinding[] members = annotation.getDeclaredMethods();
Arrays.sort(members, new Comparator<IMethodBinding>() {
@Override
public int compare(IMethodBinding o1, IMethodBinding o2) {
return o1.getName().compareTo(o2.getName());
}
});
return members;
}

/**
* Returns an alphabetically sorted list of an annotation's member values.
* This is necessary since an annotation's values can be specified in any
Expand Down

0 comments on commit ceff814

Please sign in to comment.