Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@
import com.google.devtools.j2objc.Options;
import com.google.devtools.j2objc.ast.FieldDeclaration;
import com.google.devtools.j2objc.ast.PropertyAnnotation;
import com.google.devtools.j2objc.ast.TreeUtil;
import com.google.devtools.j2objc.ast.VariableDeclarationFragment;
import com.google.devtools.j2objc.util.ElementUtil;
import com.google.devtools.j2objc.util.ErrorUtil;
import com.google.devtools.j2objc.util.NameTable;
import com.google.devtools.j2objc.util.TypeUtil;
import com.google.j2objc.annotations.Property;
import com.google.j2objc.annotations.Weak;
import java.util.Optional;
import java.util.Set;
Expand All @@ -44,6 +42,7 @@ public static Optional<String> generate(
NameTable nameTable,
TypeUtil typeUtil,
boolean parametersNonnullByDefault) {

return new PropertyGenerator(fragment, options, nameTable, typeUtil, parametersNonnullByDefault)
.build();
}
Expand All @@ -70,9 +69,14 @@ private PropertyGenerator(
this.nameTable = nameTable;
this.typeUtil = typeUtil;
this.parametersNonnullByDefault = parametersNonnullByDefault;

declaration = (FieldDeclaration) fragment.getParent();
PropertyAnnotation annotation =
(PropertyAnnotation) TreeUtil.getAnnotation(Property.class, declaration.getAnnotations());
declaration.getAnnotations().stream()
.filter(PropertyAnnotation.class::isInstance)
.map(PropertyAnnotation.class::cast)
.findFirst()
.orElse(null);
varElement = fragment.getVariableElement();
if (annotation == null
&& options.classProperties()
Expand Down Expand Up @@ -134,8 +138,11 @@ private void processAccessorAttributes(Set<String> attributes) {
if (getter != null) {
// Update getter from its Java name to its selector. This is normally the
// same since getters have no parameters, but the name may be reserved.
String getterSelector = nameTable.getMethodSelector(getter);
attributes.remove("getter=" + annotation.getGetter());
attributes.add("getter=" + nameTable.getMethodSelector(getter));
if (!getterSelector.equals(propertyName)) {
attributes.add("getter=" + getterSelector);
}
if (!ElementUtil.isSynchronized(getter)) {
attributes.add("nonatomic");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import com.google.devtools.j2objc.ast.MethodDeclaration;
import com.google.devtools.j2objc.ast.Name;
import com.google.devtools.j2objc.ast.NativeDeclaration;
import com.google.devtools.j2objc.ast.PropertyAnnotation;
import com.google.devtools.j2objc.ast.RecordDeclaration;
import com.google.devtools.j2objc.ast.TreeNode;
import com.google.devtools.j2objc.ast.VariableDeclarationFragment;
import com.google.devtools.j2objc.util.ElementUtil;
Expand Down Expand Up @@ -419,13 +421,26 @@ protected void printInstanceVariables() {

protected void printProperties() {
Iterable<VariableDeclarationFragment> fields = getAllFields();

for (VariableDeclarationFragment fragment : fields) {
VariableElement var = fragment.getVariableElement();
if (typeNode instanceof RecordDeclaration && !ElementUtil.isStatic(var)) {
// Instance files of a record are its components.

// Synthesize a declaration as if it was annotated with @Property.
FieldDeclaration componentDeclaration = new FieldDeclaration(var, null);
PropertyAnnotation componentAnnotation = new PropertyAnnotation();
componentAnnotation.getPropertyAttributes().add("readonly");
componentAnnotation.getPropertyAttributes().add("nonatomic");
componentDeclaration.addAnnotation(componentAnnotation);
fragment = componentDeclaration.getFragment();
}
PropertyGenerator.generate(fragment, options, nameTable, typeUtil, parametersNonnullByDefault)
.ifPresent(this::println);
}

if (options.classProperties() && typeNode instanceof EnumDeclaration) {
for (EnumConstantDeclaration constant : ((EnumDeclaration) typeNode).getEnumConstants()) {
if (options.classProperties() && typeNode instanceof EnumDeclaration enumDeclaration) {
for (EnumConstantDeclaration constant : enumDeclaration.getEnumConstants()) {
String accessorName = nameTable.getStaticAccessorName(constant.getVariableElement());
print("\n@property (readonly, class");
if (options.nullability()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ public void testMinimalRecord() throws IOException {
assertInTranslation(
translation, "void Point_initWithInt_withInt_(Point *self, int32_t x, int32_t y);");

// Verify accessors declared for record's members.
// Verify properties declared for record's members and
assertInTranslation(translation, "@property (readonly, nonatomic) int32_t x;");
assertInTranslation(translation, "@property (readonly, nonatomic) int32_t y;");
// also as accessor methods
assertInTranslation(translation, "- (int32_t)x;");
assertInTranslation(translation, "- (int32_t)y;");

Expand Down Expand Up @@ -105,6 +108,8 @@ public String toString() {
"Point",
"Point.h");
assertInTranslation(translation, "@interface Point : JavaLangRecord");
assertInTranslation(translation, "@property (readonly, nonatomic) int32_t x;");
assertInTranslation(translation, "@property (readonly, nonatomic) int32_t y;");
assertInTranslation(translation, "- (int32_t)x;");
assertInTranslation(translation, "- (int32_t)y;");
assertInTranslation(translation, "- (bool)isEqual:(id)o;");
Expand Down