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
36 changes: 20 additions & 16 deletions jre_emul/Classes/J2ObjC_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,34 +340,38 @@ FOUNDATION_EXPORT Class _Nullable objc_opt_class(id _Nullable obj);

#ifdef J2OBJC_STRICT_FIELD_ASSIGN

#define J2OBJC_FIELD_SETTER(CLASS, FIELD, TYPE) \
__attribute__((unused)) static inline TYPE CLASS##_set_##FIELD(CLASS *instance, TYPE value) { \
return JreStrictFieldStrongAssign(&instance->FIELD, value); \
#define J2OBJC_FIELD_SETTER(CLASS, FIELD, ...) \
__attribute__((unused)) static inline __VA_ARGS__ CLASS##_set_##FIELD(CLASS *instance, \
__VA_ARGS__ value) { \
return JreStrictFieldStrongAssign(&instance->FIELD, value); \
}

#else // J2OBJC_STRICT_FIELD_ASSIGN

#if __has_feature(objc_arc)
#define J2OBJC_FIELD_SETTER(CLASS, FIELD, TYPE) \
__attribute__((unused)) static inline TYPE CLASS##_set_##FIELD(CLASS *instance, TYPE value) { \
return instance->FIELD = value; \
#define J2OBJC_FIELD_SETTER(CLASS, FIELD, ...) \
__attribute__((unused)) static inline __VA_ARGS__ CLASS##_set_##FIELD(CLASS *instance, \
__VA_ARGS__ value) { \
return instance->FIELD = value; \
}
#else
#define J2OBJC_FIELD_SETTER(CLASS, FIELD, TYPE) \
__attribute__((unused)) static inline TYPE CLASS##_set_##FIELD(CLASS *instance, TYPE value) { \
return JreStrongAssign(&instance->FIELD, value); \
}\
__attribute__((unused)) static inline TYPE CLASS##_setAndConsume_##FIELD( \
CLASS *instance, NS_RELEASES_ARGUMENT TYPE value) { \
return JreStrongAssignAndConsume(&instance->FIELD, value); \
#define J2OBJC_FIELD_SETTER(CLASS, FIELD, ...) \
__attribute__((unused)) static inline __VA_ARGS__ CLASS##_set_##FIELD(CLASS *instance, \
__VA_ARGS__ value) { \
return JreStrongAssign(&instance->FIELD, value); \
} \
__attribute__((unused)) static inline __VA_ARGS__ CLASS##_setAndConsume_##FIELD( \
CLASS *instance, NS_RELEASES_ARGUMENT __VA_ARGS__ value) { \
return JreStrongAssignAndConsume(&instance->FIELD, value); \
}
#endif

#endif // J2OBJC_STRICT_FIELD_ASSIGN

#define J2OBJC_VOLATILE_FIELD_SETTER(CLASS, FIELD, TYPE) \
__attribute__((unused)) static inline TYPE CLASS##_set_##FIELD(CLASS *instance, TYPE value) { \
return JreVolatileStrongAssign(&instance->FIELD, value); \
#define J2OBJC_VOLATILE_FIELD_SETTER(CLASS, FIELD, ...) \
__attribute__((unused)) static inline __VA_ARGS__ CLASS##_set_##FIELD(CLASS *instance, \
__VA_ARGS__ value) { \
return JreVolatileStrongAssign(&instance->FIELD, value); \
}

/*!
Expand Down
123 changes: 63 additions & 60 deletions jre_emul/Classes/J2ObjC_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,25 @@ CF_EXTERN_C_END
* @param FIELD The name of the static variable prefixed with an underscore.
* @param TYPE The type of the static variable.
*/
#define J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_get##FIELD(void) { \
CLASS##_initialize(); \
return CLASS##FIELD; \
#define J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_get##FIELD(void) { \
CLASS##_initialize(); \
return CLASS##FIELD; \
}
#define J2OBJC_STATIC_FIELD_PRIMITIVE_REF_GETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE *CLASS##_getRef##FIELD(void) { \
CLASS##_initialize(); \
return &CLASS##FIELD; \
#define J2OBJC_STATIC_FIELD_PRIMITIVE_REF_GETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ *CLASS##_getRef##FIELD(void) { \
CLASS##_initialize(); \
return &CLASS##FIELD; \
}
#define J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_GETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_get##FIELD(void) { \
CLASS##_initialize(); \
return __c11_atomic_load(&CLASS##FIELD, __ATOMIC_SEQ_CST); \
#define J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_GETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_get##FIELD(void) { \
CLASS##_initialize(); \
return __c11_atomic_load(&CLASS##FIELD, __ATOMIC_SEQ_CST); \
}
#define J2OBJC_STATIC_FIELD_OBJ_VOLATILE_GETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_get##FIELD(void) { \
CLASS##_initialize(); \
return JreLoadVolatileId(&CLASS##FIELD); \
#define J2OBJC_STATIC_FIELD_OBJ_VOLATILE_GETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_get##FIELD(void) { \
CLASS##_initialize(); \
return JreLoadVolatileId(&CLASS##FIELD); \
}

/*!
Expand All @@ -79,38 +79,39 @@ CF_EXTERN_C_END
* @param FIELD The name of the static variable prefixed with an underscore.
* @param TYPE The type of the static variable.
*/
#define J2OBJC_STATIC_FIELD_PRIMITIVE_SETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_set##FIELD(TYPE value) { \
CLASS##_initialize(); \
return CLASS##FIELD = value; \
#define J2OBJC_STATIC_FIELD_PRIMITIVE_SETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_set##FIELD(__VA_ARGS__ value) { \
CLASS##_initialize(); \
return CLASS##FIELD = value; \
}
#define J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_SETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_set##FIELD(TYPE value) { \
CLASS##_initialize(); \
__c11_atomic_store(&CLASS##FIELD, value, __ATOMIC_SEQ_CST); \
return value; \
#define J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_SETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_set##FIELD(__VA_ARGS__ value) { \
CLASS##_initialize(); \
__c11_atomic_store(&CLASS##FIELD, value, __ATOMIC_SEQ_CST); \
return value; \
}
#if __has_feature(objc_arc)
#define J2OBJC_STATIC_FIELD_OBJ_SETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_set##FIELD(TYPE value) { \
CLASS##_initialize(); \
return CLASS##FIELD = value; \
#define J2OBJC_STATIC_FIELD_OBJ_SETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_set##FIELD(__VA_ARGS__ value) { \
CLASS##_initialize(); \
return CLASS##FIELD = value; \
}
#else
#define J2OBJC_STATIC_FIELD_OBJ_SETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_set##FIELD(TYPE value) { \
CLASS##_initialize(); \
return JreStrongAssign(&CLASS##FIELD, value); \
} \
__attribute__((always_inline)) inline TYPE CLASS##_setAndConsume##FIELD(TYPE value) { \
CLASS##_initialize(); \
return JreStrongAssignAndConsume(&CLASS##FIELD, value); \
#define J2OBJC_STATIC_FIELD_OBJ_SETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_set##FIELD(__VA_ARGS__ value) { \
CLASS##_initialize(); \
return JreStrongAssign(&CLASS##FIELD, value); \
} \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_setAndConsume##FIELD( \
__VA_ARGS__ value) { \
CLASS##_initialize(); \
return JreStrongAssignAndConsume(&CLASS##FIELD, value); \
}
#endif
#define J2OBJC_STATIC_FIELD_OBJ_VOLATILE_SETTER(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_set##FIELD(TYPE value) { \
CLASS##_initialize(); \
return JreVolatileStrongAssign(&CLASS##FIELD, value); \
#define J2OBJC_STATIC_FIELD_OBJ_VOLATILE_SETTER(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_set##FIELD(__VA_ARGS__ value) { \
CLASS##_initialize(); \
return JreVolatileStrongAssign(&CLASS##FIELD, value); \
}

/*!
Expand All @@ -131,25 +132,27 @@ CF_EXTERN_C_END
* @param TYPE The type of the static variable.
*/
// Java constants do not cause static initialization.
#define J2OBJC_STATIC_FIELD_CONSTANT(CLASS, FIELD, TYPE) \
__attribute__((always_inline)) inline TYPE CLASS##_get_##FIELD(void) { return CLASS##_##FIELD; }
#define J2OBJC_STATIC_FIELD_PRIMITIVE(CLASS, FIELD, TYPE) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, TYPE) \
J2OBJC_STATIC_FIELD_PRIMITIVE_SETTER(CLASS, _##FIELD, TYPE) \
J2OBJC_STATIC_FIELD_PRIMITIVE_REF_GETTER(CLASS, _##FIELD, TYPE)
#define J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE(CLASS, FIELD, TYPE) \
J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_GETTER(CLASS, _##FIELD, TYPE) \
J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_SETTER(CLASS, _##FIELD, TYPE)
#define J2OBJC_STATIC_FIELD_PRIMITIVE_FINAL(CLASS, FIELD, TYPE) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, TYPE)
#define J2OBJC_STATIC_FIELD_OBJ(CLASS, FIELD, TYPE) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, TYPE) \
J2OBJC_STATIC_FIELD_OBJ_SETTER(CLASS, _##FIELD, TYPE)
#define J2OBJC_STATIC_FIELD_OBJ_VOLATILE(CLASS, FIELD, TYPE) \
J2OBJC_STATIC_FIELD_OBJ_VOLATILE_GETTER(CLASS, _##FIELD, TYPE) \
J2OBJC_STATIC_FIELD_OBJ_VOLATILE_SETTER(CLASS, _##FIELD, TYPE)
#define J2OBJC_STATIC_FIELD_OBJ_FINAL(CLASS, FIELD, TYPE) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, TYPE)
#define J2OBJC_STATIC_FIELD_CONSTANT(CLASS, FIELD, ...) \
__attribute__((always_inline)) inline __VA_ARGS__ CLASS##_get_##FIELD(void) { \
return CLASS##_##FIELD; \
}
#define J2OBJC_STATIC_FIELD_PRIMITIVE(CLASS, FIELD, ...) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, __VA_ARGS__) \
J2OBJC_STATIC_FIELD_PRIMITIVE_SETTER(CLASS, _##FIELD, __VA_ARGS__) \
J2OBJC_STATIC_FIELD_PRIMITIVE_REF_GETTER(CLASS, _##FIELD, __VA_ARGS__)
#define J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE(CLASS, FIELD, ...) \
J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_GETTER(CLASS, _##FIELD, __VA_ARGS__) \
J2OBJC_STATIC_FIELD_PRIMITIVE_VOLATILE_SETTER(CLASS, _##FIELD, __VA_ARGS__)
#define J2OBJC_STATIC_FIELD_PRIMITIVE_FINAL(CLASS, FIELD, ...) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, __VA_ARGS__)
#define J2OBJC_STATIC_FIELD_OBJ(CLASS, FIELD, ...) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, __VA_ARGS__) \
J2OBJC_STATIC_FIELD_OBJ_SETTER(CLASS, _##FIELD, __VA_ARGS__)
#define J2OBJC_STATIC_FIELD_OBJ_VOLATILE(CLASS, FIELD, ...) \
J2OBJC_STATIC_FIELD_OBJ_VOLATILE_GETTER(CLASS, _##FIELD, __VA_ARGS__) \
J2OBJC_STATIC_FIELD_OBJ_VOLATILE_SETTER(CLASS, _##FIELD, __VA_ARGS__)
#define J2OBJC_STATIC_FIELD_OBJ_FINAL(CLASS, FIELD, ...) \
J2OBJC_STATIC_FIELD_BASIC_GETTER(CLASS, _##FIELD, __VA_ARGS__)

/*!
* Defines the getter for an enum constant. For enum class "FooEnum" and constant "BAR"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,16 @@ private String getStringRepresentation(Set<String> attributes) {
buffer.append('(').append(PropertyAnnotation.toAttributeString(attributes)).append(") ");
}

String objcType = nameTable.getObjCType(varType);
TypeElement declaringClass = ElementUtil.getDeclaringClass(varElement);
boolean allowGenerics = !typeUtil.isProtoClass(varType);
boolean enableGenerics =
allowGenerics
&& (options.asObjCGenericDecl()
|| TypeUtil.hasGenerateObjectiveCGenerics(varType)
|| (declaringClass != null
&& TypeUtil.hasGenerateObjectiveCGenerics(declaringClass)))
&& (declaringClass == null || !TypeUtil.isInterface(declaringClass.asType()));
String objcType = nameTable.getObjCTypeDeclaration(varType, enableGenerics, declaringClass);
buffer.append(objcType);
if (!objcType.endsWith("*")) {
buffer.append(' ');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,14 @@ protected void printStaticAccessors() {
VariableElement var = fragment.getVariableElement();
TypeMirror type = var.asType();
String accessorName = nameTable.getStaticAccessorName(var);
String objcType = paddedType(nameTable.getObjCTypeDeclaration(type), var).trim();
boolean allowGenerics = !typeUtil.isProtoClass(type);
boolean enableGenerics =
allowGenerics
&& (generateObjectiveCGenerics(type)
|| generateObjectiveCGenerics(typeElement.asType()));
String objcType =
paddedType(nameTable.getObjCTypeDeclaration(type, enableGenerics, typeElement), var)
.trim();
TypeElement declaringClass = ElementUtil.getDeclaringClass(var);
String baseName = nameTable.getVariableBaseName(var);
ExecutableElement getter =
Expand Down Expand Up @@ -579,7 +586,12 @@ protected void printStaticFieldDeclaration(
private void printStaticFieldFullDeclaration(VariableDeclarationFragment fragment) {
VariableElement var = fragment.getVariableElement();
boolean isVolatile = ElementUtil.isVolatile(var);
String objcType = nameTable.getObjCTypeDeclaration(var.asType());
boolean allowGenerics = !typeUtil.isProtoClass(var.asType());
boolean enableGenerics =
allowGenerics
&& (generateObjectiveCGenerics(var.asType())
|| generateObjectiveCGenerics(typeElement.asType()));
String objcType = nameTable.getObjCTypeDeclaration(var.asType(), enableGenerics, typeElement);
String objcTypePadded = paddedType(objcType, var);
String declType = paddedType(getDeclarationType(var), var);
String name = nameTable.getVariableShortName(var);
Expand Down Expand Up @@ -610,8 +622,11 @@ private void printStaticFieldFullDeclaration(VariableDeclarationFragment fragmen
printStaticFieldDeclaration(
fragment, UnicodeUtils.format("%s%s_%s", declType, typeName, name));
}
printf(
"J2OBJC_STATIC_FIELD%s(%s, %s, %s)\n", qualifiers, typeName, name, objcTypePadded.trim());
String macroTypeArg = objcTypePadded.trim();
if (macroTypeArg.contains(",")) {
macroTypeArg = "J2OBJC_ARG(" + macroTypeArg + ')';
}
printf("J2OBJC_STATIC_FIELD%s(%s, %s, %s)\n", qualifiers, typeName, name, macroTypeArg);
}

// Overridden in TypePrivateDeclarationGenerator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,14 @@ private void printStaticFieldExterns() {
}
for (VariableDeclarationFragment fragment : getStaticFields()) {
VariableElement var = fragment.getVariableElement();
String objcTypePadded = paddedType(nameTable.getObjCTypeDeclaration(var.asType()), var);
boolean allowGenerics = !typeUtil.isProtoClass(var.asType());
boolean enableGenerics =
allowGenerics
&& (generateObjectiveCGenerics(var.asType())
|| generateObjectiveCGenerics(typeElement.asType()));
String objcTypePadded =
paddedType(
nameTable.getObjCTypeDeclaration(var.asType(), enableGenerics, typeElement), var);
String name = nameTable.getVariableShortName(var);
newline();
printf("extern %s%s_get_%s(void);\n", objcTypePadded, typeName, name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,11 @@ public boolean visit(AnnotationTypeMemberDeclaration node) {

@Override
public boolean visit(FieldDeclaration node) {
if (filter.include(node) && includeInnerTypes) {
if (filter.include(node)) {
addForwardDecl(node.getTypeMirror());
for (TypeMirror fieldGeneric : objCForwardDeclaredGenericParameters(node.getTypeMirror())) {
addForwardDecl(fieldGeneric);
}
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,4 +422,25 @@ public void testProtoDeclaration() throws IOException {
assertInTranslation(testHeader, "@interface ComGoogleProtobufTest : NSObject");
assertInTranslation(testHeader, "- (id)getWithId:(id)input;");
}

public void testStaticPropertyGenerics() throws IOException {
options.setClassProperties(true);
addSourceFile(
"import com.google.j2objc.annotations.GenerateObjectiveCGenerics; "
+ "@GenerateObjectiveCGenerics "
+ "public class Box<T> {}",
"Box.java");
addSourceFile(
"import com.google.j2objc.annotations.GenerateObjectiveCGenerics; "
+ "@GenerateObjectiveCGenerics "
+ "public class Test {"
+ " public static final Box<String> STRING_BOX = new Box<>();"
+ "}",
"Test.java");

String testSystemHeader = translateSourceFile("Test", "Test.h");
assertInTranslation(
testSystemHeader, "@property (readonly, class, strong) Box<NSString *> *STRING_BOX");
assertInTranslation(testSystemHeader, "inline Box<NSString *> *Test_get_STRING_BOX(void);");
}
}