Skip to content

Commit

Permalink
Merge pull request #644 from @mbaron. Added --swift-friendly flag, an…
Browse files Browse the repository at this point in the history
…d moved toNSEnum() support behind it.

	Change on 2015/10/19 by tball <tball@google.com>
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=105792244
  • Loading branch information
tomball committed Oct 19, 2015
1 parent e5fcbf7 commit ac3dcbe
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 11 deletions.
3 changes: 3 additions & 0 deletions doc/man/j2objc.1
Expand Up @@ -119,6 +119,9 @@ annotation, unless its value is known to be compatible.
.BI \-\-strip\-reflection
Do not generate metadata needed for Java reflection.
.TP
.BI \-\-swift\-friendly
Generate code that facilitates Swift importing.
.TP
\fB\-t\fR, \fB\-\-timing\-info\fR
Print time spent in translation steps.
.TP
Expand Down
17 changes: 17 additions & 0 deletions translator/src/main/java/com/google/devtools/j2objc/Options.java
Expand Up @@ -88,6 +88,7 @@ public class Options {
private List<String> headerMappingFiles = null;
private String processors = null;
private boolean disallowInheritedConstructors = false;
private boolean swiftFriendly = false;

private PackagePrefixes packagePrefixes = new PackagePrefixes();

Expand Down Expand Up @@ -361,6 +362,8 @@ private String[] loadInternal(String[] args) throws IOException {
Integer.parseInt(arg.substring(BATCH_PROCESSING_MAX_FLAG.length()));
} else if (arg.equals("--static-accessor-methods")) {
staticAccessorMethods = true;
} else if (arg.equals("--swift-friendly")) {
swiftFriendly = true;
} else if (arg.equals("-processor")) {
if (++nArg == args.length) {
usage("-processor requires an argument");
Expand Down Expand Up @@ -420,6 +423,10 @@ else if (arg.equals("--final-methods-as-functions")
memoryManagementOption = MemoryManagementOption.REFERENCE_COUNTING;
}

if (swiftFriendly) {
staticAccessorMethods = true;
}

// Pull source version from system properties if it is not passed with -source flag.
if (sourceVersion == null) {
sourceVersion = System.getProperty("java.version").substring(0, 3);
Expand Down Expand Up @@ -821,4 +828,14 @@ public static boolean disallowInheritedConstructors() {
public static void setDisallowInheritedConstructors(boolean b) {
instance.disallowInheritedConstructors = b;
}

public static boolean swiftFriendly() {
return instance.swiftFriendly;
}

@VisibleForTesting
public static void setSwiftFriendly(boolean b) {
instance.swiftFriendly = b;
instance.staticAccessorMethods = b;
}
}
Expand Up @@ -128,16 +128,27 @@ public void endVisit(SuperConstructorInvocation node) {
private void addExtraNativeDecls(EnumDeclaration node) {
String typeName = nameTable.getFullName(node.getTypeBinding());
int numConstants = node.getEnumConstants().size();
boolean swiftFriendly = Options.swiftFriendly();

String header = String.format(
StringBuilder header = new StringBuilder();
header.append(String.format(
"+ (IOSObjectArray *)values;\n"
+ "FOUNDATION_EXPORT IOSObjectArray *%s_values();\n\n"
+ "+ (%s *)valueOfWithNSString:(NSString *)name;\n"
+ "FOUNDATION_EXPORT %s *%s_valueOfWithNSString_(NSString *name);\n\n"
+ "- (id)copyWithZone:(NSZone *)zone;\n", typeName, typeName, typeName, typeName);
+ "- (id)copyWithZone:(NSZone *)zone;\n", typeName, typeName, typeName, typeName));

StringBuilder sb = new StringBuilder();
sb.append(String.format(
// Strip enum type suffix.
String bareTypeName =
typeName.endsWith("Enum") ? typeName.substring(0, typeName.length() - 4) : typeName;

if (swiftFriendly) {
header.append(String.format(
"- (%s)toNSEnum;\n", bareTypeName));
}

StringBuilder implementation = new StringBuilder();
implementation.append(String.format(
"IOSObjectArray *%s_values() {\n"
+ " %s_initialize();\n"
+ " return [IOSObjectArray arrayWithObjects:%s_values_ count:%s type:%s_class_()];\n"
Expand All @@ -146,12 +157,12 @@ private void addExtraNativeDecls(EnumDeclaration node) {
+ " return %s_values();\n"
+ "}\n\n", typeName, typeName, typeName, numConstants, typeName, typeName));

sb.append(String.format(
implementation.append(String.format(
"+ (%s *)valueOfWithNSString:(NSString *)name {\n"
+ " return %s_valueOfWithNSString_(name);\n"
+ "}\n\n", typeName, typeName));

sb.append(String.format(
implementation.append(String.format(
"%s *%s_valueOfWithNSString_(NSString *name) {\n"
+ " %s_initialize();\n"
+ " for (int i = 0; i < %s; i++) {\n"
Expand All @@ -161,19 +172,29 @@ private void addExtraNativeDecls(EnumDeclaration node) {
+ " }\n"
+ " }\n", typeName, typeName, typeName, numConstants, typeName, typeName));
if (Options.useReferenceCounting()) {
sb.append(
implementation.append(
" @throw [[[JavaLangIllegalArgumentException alloc] initWithNSString:name]"
+ " autorelease];\n");
} else {
sb.append(" @throw [[JavaLangIllegalArgumentException alloc] initWithNSString:name];\n");
implementation.append(
" @throw [[JavaLangIllegalArgumentException alloc] initWithNSString:name];\n");
}
implementation.append(" return nil;\n}\n\n");

if (swiftFriendly) {
implementation.append(String.format(
"- (%s)toNSEnum {\n"
+ " return (%s)[self ordinal];\n"
+ "}\n\n", bareTypeName, bareTypeName));
}
sb.append(" return nil;\n}\n\n");

// Enum constants needs to implement NSCopying. Being singletons, they
// can just return self, as long the retain count is incremented.
String selfString = Options.useReferenceCounting() ? "[self retain]" : "self";
sb.append(String.format("- (id)copyWithZone:(NSZone *)zone {\n return %s;\n}\n", selfString));
implementation.append(
String.format("- (id)copyWithZone:(NSZone *)zone {\n return %s;\n}\n", selfString));

node.getBodyDeclarations().add(new NativeDeclaration(header, sb.toString()));
node.getBodyDeclarations().add(new NativeDeclaration(header.toString(),
implementation.toString()));
}
}
Expand Up @@ -70,6 +70,7 @@ Other options:\n\
--strip-gwt-incompatible Removes methods that are marked with a GwtIncompatible\
\n annotation, unless its value is known to be compatible.\n\
--strip-reflection Do not generate metadata needed for Java reflection.\n\
--swift-friendly Generate code that facilitates Swift importing.\n\
-t, --timing-info Print time spent in translation steps.\n\
-use-arc Generate Objective-C code to support Automatic\
\n Reference Counting (ARC).\n\
Expand Down
Expand Up @@ -101,6 +101,16 @@ public void testEnumConstantAccessorMethods() throws IOException {
assertTranslation(translation, "+ (TestEnum *)EOF_;");
}

// Verify that accessor methods for enum constants are generated by --swift-friendly flag.
public void testSwiftFriendlyEnumConstantAccessorMethods() throws IOException {
Options.setSwiftFriendly(true);
String source = "enum Test { ONE, TWO, EOF }"; // EOF is a reserved name.
String translation = translateSourceFile(source, "Test", "Test.h");
assertTranslation(translation, "+ (TestEnum *)ONE;");
assertTranslation(translation, "+ (TestEnum *)TWO;");
assertTranslation(translation, "+ (TestEnum *)EOF_;");
}

// Verify that accessor methods for enum constants are not generated by default.
public void testNoEnumConstantAccessorMethods() throws IOException {
String source = "enum Test { ONE, TWO, EOF_ }";
Expand Down
Expand Up @@ -15,6 +15,7 @@
package com.google.devtools.j2objc.translate;

import com.google.devtools.j2objc.GenerationTest;
import com.google.devtools.j2objc.Options;

import java.io.IOException;

Expand All @@ -35,4 +36,20 @@ public void testGenericEnumConstructor() throws IOException {
assertTranslation(translation,
"TestEnum_A = new_TestEnum_initWithId_withNSString_withInt_(@\"foo\", @\"A\", 0);");
}

public void testNoDefaultToNsEnumConversion() throws Exception {
String translation = translateSourceFile("enum Test { A }", "Test", "Test.m");
assertNotInTranslation(translation, "toNSEnum");
}

public void testToNsEnumConversion() throws Exception {
Options.setSwiftFriendly(true);
String translation = translateSourceFile("enum Test { A }", "Test", "Test.m");
assertTranslatedLines(translation,
"- (Test)toNSEnum {",
" return (Test)[self ordinal];",
"}");
}
}


0 comments on commit ac3dcbe

Please sign in to comment.