current commit

This commit is contained in:
aFedasenka 2012-10-09 15:58:28 +02:00
parent 23183c6725
commit 66a5fb8b9f
5 changed files with 772 additions and 14 deletions

View file

@ -9,8 +9,7 @@ import org.eclipse.jdt.core.dom.CompilationUnit;
import com.google.common.io.Files;
import com.google.devtools.j2cpp.gen.CppHeaderGenerator;
//import com.google.devtools.j2objc.J2ObjC.Language;
//import com.google.devtools.j2objc.gen.ObjectiveCImplementationGenerator;
import com.google.devtools.j2cpp.gen.CppImplementationGenerator;
public abstract class CppGenerationTest extends GenerationTest {
@ -22,11 +21,11 @@ public abstract class CppGenerationTest extends GenerationTest {
System.out.println("-----------------------------HEADER-----------------");
System.out.println(getTranslatedFile(type+".h"));
System.out.println();
// TODO commented for testing a header only
// System.out.println();
// System.out.println("------------------------------------------------");
// System.out.println("-------------------SOURCE-------------------");
// System.out.println(getTranslatedFile(type+".m"));
System.out.println();
System.out.println("------------------------------------------------");
System.out.println("-------------------SOURCE-------------------");
System.out.println(getTranslatedFile(type+".cpp"));
}
protected void assertNoCompilationErrors(CompilationUnit unit) {
@ -45,6 +44,6 @@ public abstract class CppGenerationTest extends GenerationTest {
assertNoCompilationErrors(unit);
String sourceName = typeName + ".java";
CppHeaderGenerator.generate(sourceName, source, unit);
// ObjectiveCImplementationGenerator.generate(sourceName, Language.OBJECTIVE_C, unit, source);
CppImplementationGenerator.generate(sourceName, unit, source);
}
}

View file

@ -31,6 +31,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.devtools.j2cpp.util.NameTableCpp;
import com.google.devtools.j2objc.util.NameTable;
import com.google.devtools.j2objc.J2ObjC;
import com.google.devtools.j2objc.Options;
@ -79,7 +80,7 @@ public class CppHeaderGenerator extends CppSourceFileGenerator{
@Override
public void generate(TypeDeclaration node) {
String typeName = NameTable.getFullName(node);
String typeName = NameTableCpp.getFullName(node);
String superName = NameTable.getSuperClassName(node);
//DONE if extends superclass other than Object
@ -270,7 +271,7 @@ public class CppHeaderGenerator extends CppSourceFileGenerator{
}
protected String createForwardDeclaration(String typeName, boolean isInterface) {
return String.format("@%s %s;", isInterface ? "protocol" : "class", typeName);
return String.format("@%s %s;", isInterface ? "TODO: change to abstract class \ninterface" : "class", typeName);
}
protected String createImport(ImportCollector.Import imp) {

View file

@ -0,0 +1,759 @@
/*
* Copyright 2011 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devtools.j2cpp.gen;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
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.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.devtools.j2objc.J2ObjC;
import com.google.devtools.j2objc.Options;
import com.google.devtools.j2objc.gen.HiddenFieldDetector;
import com.google.devtools.j2objc.gen.ObjectiveCSourceFileGenerator;
import com.google.devtools.j2objc.gen.StatementGenerator;
import com.google.devtools.j2objc.types.IOSMethod;
import com.google.devtools.j2objc.types.ImplementationImportCollector;
import com.google.devtools.j2objc.types.ImportCollector;
import com.google.devtools.j2objc.types.Types;
import com.google.devtools.j2objc.util.ErrorReportingASTVisitor;
import com.google.devtools.j2objc.util.NameTable;
/**
* Generates C++ implementation (.m) files from compilation units.
*
* @author Tom Ball
*/
public class CppImplementationGenerator extends ObjectiveCSourceFileGenerator {
private Set<IVariableBinding> fieldHiders;
private final String suffix;
/**
* Generate an C++ implementation file for each type declared in a
* specified compilation unit.
*/
public static void generate(String fileName, CompilationUnit unit, String source) {
CppImplementationGenerator implementationGenerator = new CppImplementationGenerator(fileName, unit, source);
implementationGenerator.generate(unit);
}
private CppImplementationGenerator(String fileName, CompilationUnit unit, String source) {
super(fileName, source, unit, Options.emitLineDirectives());
fieldHiders = HiddenFieldDetector.getFieldNameConflicts(unit);
suffix = ".cpp";
}
@Override
protected String getSuffix() {
return suffix;
}
public void generate(CompilationUnit unit) {
println(J2ObjC.getFileHeader(getSourceFileName()));
if (needsPrinting(unit)) {
printStart(getSourceFileName());
printImports(unit);
unit.accept(new ErrorReportingASTVisitor() {
@Override
public boolean visit(TypeDeclaration node) {
generate(node);
return true;
}
@Override
public boolean visit(EnumDeclaration node) {
generate(node);
return true;
}
});
} else {
// Print a dummy C function so compiled object file is valid.
@SuppressWarnings("unchecked")
List<AbstractTypeDeclaration> types = unit.types(); // safe by definition
if (!types.isEmpty()) {
printf("void %s_unused() {}\n", NameTable.getFullName(types.get(0)));
}
}
save(unit);
}
private boolean needsPrinting(CompilationUnit unit) {
final boolean[] result = { false };
unit.accept(new ErrorReportingASTVisitor() {
@Override
public boolean visit(TypeDeclaration node) {
if (!node.isInterface()) {
result[0] = true; // always print concrete types
return false;
}
return true;
}
@Override
public boolean visit(EnumDeclaration node) {
result[0] = true; // always print enums
return false;
}
@Override
public boolean visit(AnnotationTypeDeclaration node) {
return false; // never print annotations
}
@Override
public void endVisit(MethodDeclaration node) {
// Only print protocols if they have static constants.
if (isInterfaceConstantAccessor(Types.getMethodBinding(node))) {
result[0] = true;
}
}
});
return result[0];
}
@Override
public void generate(TypeDeclaration node) {
List<IMethodBinding> testMethods = null;
if (Types.isJUnitTest(Types.getTypeBinding(node))) {
testMethods = findTestMethods(node);
}
syncLineNumbers(node.getName()); // avoid doc-comment
fieldHiders = HiddenFieldDetector.getFieldNameConflicts(node);
if (node.isInterface()) {
printStaticInterface(node);
} else {
String typeName = NameTable.getFullName(node);
printf("class %s {\n\n", typeName);
printStaticVars(Lists.newArrayList(node.getFields()));
printProperties(node.getFields());
printMethods(node);
printObjCTypeMethod(node);
println("}\n");
// Generate main method, if declared.
MethodDeclaration main = null;
for (MethodDeclaration m : node.getMethods()) {
if (isMainMethod(m)) {
main = m;
break;
}
}
newline();
if (main != null || (testMethods != null && Options.generateTestMain())) {
printMainMethod(main, typeName, testMethods);
}
}
}
private List<IMethodBinding> findTestMethods(TypeDeclaration node) {
ITypeBinding type = Types.getTypeBinding(node);
List<IMethodBinding> tests = Lists.newArrayList();
while (type != null) {
for (IMethodBinding md : type.getDeclaredMethods()) {
int modifiers = md.getModifiers();
if (Modifier.isPublic(modifiers)) {
if (md.getName().startsWith("test") && md.getParameterTypes().length == 0) {
tests.add(md);
}
}
}
type = type.getSuperclass();
}
return tests.isEmpty() ? null : tests;
}
@Override
protected void generate(AnnotationTypeDeclaration node) {
// No implementation for annotations.
}
private void printMethods(TypeDeclaration node) {
printMethods(Lists.newArrayList(node.getMethods()));
// If node implements CharSequence, add forwarding method from the
// sequenceDescription method to description (toString()). See
// JavaToIOSMethodTranslator.loadCharSequenceMethods() for details.
ITypeBinding binding = Types.getTypeBinding(node);
for (ITypeBinding interfaze : binding.getInterfaces()) {
if (interfaze.getQualifiedName().equals("java.lang.CharSequence")) {
println("- (NSString *)description {\n return [self sequenceDescription];\n}\n");
}
}
// If node defines a primitive number wrapper, add a getValue() method.
// This is required by iOS 5.0 to support cloning these types.
if (Types.isJavaNumberType(binding)) {
ITypeBinding primitiveType = Types.getPrimitiveType(binding);
if (primitiveType != null) {
// All java.lang primitive type wrappers have a "value" field.
printf("- (void)getValue:(void *)buffer {\n *((%s *) buffer) = value_;\n}\n\n",
NameTable.getFullName(primitiveType));
}
}
}
private void printStaticInterface(TypeDeclaration node) {
// Print implementation for static constants, if any.
boolean needsPrinting = false;
List<MethodDeclaration> methods = Lists.newArrayList(node.getMethods());
for (MethodDeclaration m : methods) {
if (isInterfaceConstantAccessor(Types.getMethodBinding(m))) {
needsPrinting = true;
break;
}
}
if (needsPrinting) {
printf("\n@implementation %s\n\n", NameTable.getFullName(node));
printStaticVars(Lists.newArrayList(node.getFields()));
for (MethodDeclaration m : methods) {
IMethodBinding binding = Types.getMethodBinding(m);
if (binding.isSynthetic() || isInterfaceConstantAccessor(binding)) {
printMethod(m);
}
}
println("@end");
}
}
@Override
protected void generate(EnumDeclaration node) {
@SuppressWarnings("unchecked")
List<EnumConstantDeclaration> constants = node.enumConstants(); // safe by definition
List<MethodDeclaration> methods = Lists.newArrayList();
List<FieldDeclaration> fields = Lists.newArrayList();
MethodDeclaration initializeMethod = null;
@SuppressWarnings("unchecked")
List<BodyDeclaration> declarations = node.bodyDeclarations(); // safe by definition
for (BodyDeclaration decl : declarations) {
if (decl instanceof FieldDeclaration) {
fields.add((FieldDeclaration) decl);
} else if (decl instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) decl;
if (md.getName().getIdentifier().equals("initialize")) {
initializeMethod = md;
} else {
methods.add(md);
}
}
}
syncLineNumbers(node.getName()); // avoid doc-comment
String typeName = NameTable.getFullName(node);
for (EnumConstantDeclaration constant : constants) {
printf("static %s *%s_%s;\n", typeName, typeName, NameTable.getName(constant.getName()));
}
printf("IOSObjectArray *%s_values;\n", typeName);
newline();
printf("@implementation %s\n\n", typeName);
printStaticVars(fields);
for (EnumConstantDeclaration constant : constants) {
String name = NameTable.getName(constant.getName());
printf("+ (%s *)%s {\n", typeName, name);
printf(" return %s_%s;\n", typeName, name);
println("}");
}
newline();
// 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";
printf("- (id)copyWithZone:(NSZone *)zone {\n return %s;\n}\n\n", selfString);
printProperties(fields.toArray(new FieldDeclaration[0]));
printMethods(methods);
printf("+ (void)initialize {\n if (self == [%s class]) {\n", typeName);
for (int i = 0; i < constants.size(); i++) {
EnumConstantDeclaration constant = constants.get(i);
@SuppressWarnings("unchecked")
List<Expression> args = constant.arguments(); // safe by definition
String name = NameTable.getName(constant.getName());
String constantTypeName =
NameTable.getFullName(Types.getMethodBinding(constant).getDeclaringClass());
printf(" %s_%s = [[%s alloc] init", typeName, name, constantTypeName);
boolean isSimpleEnum = constantTypeName.equals(typeName);
// Common-case: no extra fields and no constant anonymous classes.
if (args.isEmpty() && isSimpleEnum) {
printf("WithNSString:@\"%s_%s\" withInt:%d];\n", typeName.replace("Enum", ""), name, i);
} else {
String argString = StatementGenerator.generateArguments(Types.getMethodBinding(constant),
args, fieldHiders, getBuilder().getCurrentLine());
print(argString);
if (args.isEmpty()) {
print("With");
} else {
print(" with");
}
printf("NSString:@\"%s_%s\" withInt:%d];\n", typeName.replace("Enum", ""), name, i);
}
}
printf(" %s_values = [[IOSObjectArray alloc] initWithObjects:(id[]){ ", typeName);
for (EnumConstantDeclaration constant : constants) {
printf("%s_%s, ", typeName, NameTable.getName(constant.getName()));
}
printf("nil } count:%d type:[IOSClass classWithClass:[%s class]]];\n",
constants.size(), typeName);
if (initializeMethod != null) {
@SuppressWarnings("unchecked")
List<Statement> stmts = initializeMethod.getBody().statements(); // safe by definition
for (Statement s : stmts) {
printf(" %s", StatementGenerator.generate(s, fieldHiders, false,
getBuilder().getCurrentLine()));
}
}
println(" }\n}\n");
// Print generated values and valueOf methods.
println("+ (IOSObjectArray *)values {");
printf(" return [IOSObjectArray arrayWithArray:%s_values];\n", typeName);
println("}\n");
printf("+ (%s *)valueOfWithNSString:(NSString *)name {\n", typeName);
printf(" for (int i = 0; i < [%s_values count]; i++) {\n", typeName);
printf(" %s *e = [%s_values objectAtIndex:i];\n", typeName, typeName);
printf(" if ([name isEqual:[e name]]) {\n");
printf(" return e;\n");
printf(" }\n");
printf(" }\n");
printf(" @throw [[JavaLangIllegalArgumentException alloc] initWithNSString:name];\n");
printf(" return nil;\n");
println("}\n");
println("@end");
}
@Override
protected String methodDeclaration(MethodDeclaration m) {
int modifiers = m.getModifiers();
if ((modifiers & Modifier.NATIVE) > 0) {
return super.methodDeclaration(m) + " " + extractNativeMethodBody(m) + "\n\n";
}
String methodBody = generateMethodBody(m);
return super.methodDeclaration(m) + " " + reindent(methodBody) + "\n\n";
}
@Override
protected String mappedMethodDeclaration(MethodDeclaration method, IOSMethod mappedMethod) {
String methodBody;
if ((method.getModifiers() & Modifier.NATIVE) > 0) {
methodBody = extractNativeMethodBody(method);
} else {
methodBody = generateMethodBody(method);
}
return super.mappedMethodDeclaration(method, mappedMethod)
+ " " + reindent(methodBody) + "\n\n";
}
private String generateMethodBody(MethodDeclaration m) {
if (Modifier.isAbstract(m.getModifiers())) {
// Generate a body which throws a NSInvalidArgumentException.
String body =
"{\n // can't call an abstract method\n " +
"[self doesNotRecognizeSelector:_cmd];\n ";
if (!Types.isVoidType(m.getReturnType2())) {
body += "return 0;\n"; // Never executes, but avoids a gcc warning.
}
return body + "}";
}
// generate a normal method body
String methodBody = generateStatement(m.getBody(), false);
if (Types.hasAutoreleasePoolAnnotation(Types.getBinding(m))) {
return reindent(
"{\nNSAutoreleasePool *pool__ = [[NSAutoreleasePool alloc] init];\n" +
methodBody +
"[pool__ release];\n}");
} else {
return methodBody;
}
}
@Override
protected String getParameterName(SingleVariableDeclaration param) {
String name = super.getParameterName(param);
IVariableBinding binding = param.resolveBinding();
return binding != null && fieldHiders.contains(binding) ? name + "Arg" : name;
}
@Override
protected String constructorDeclaration(MethodDeclaration m) {
String methodBody;
IMethodBinding binding = Types.getMethodBinding(m);
@SuppressWarnings("unchecked")
List<Statement> statements = m.getBody().statements();
if (binding.getDeclaringClass().isEnum()) {
return enumConstructorDeclaration(m, statements, binding);
} else if (statements.isEmpty()) {
methodBody = "{\nreturn (self = [super init]);\n}";
} else if (statements.size() == 1 &&
(statements.get(0) instanceof ConstructorInvocation ||
statements.get(0) instanceof SuperConstructorInvocation)) {
methodBody = "{\nreturn " + generateStatement(statements.get(0), false, true) + ";\n}";
} else {
StringBuffer sb = new StringBuffer();
Statement first = statements.get(0);
boolean firstPrinted = false;
sb.append("{\nif ((self = ");
if (first instanceof ConstructorInvocation ||
first instanceof SuperConstructorInvocation) {
sb.append(generateStatement(first, false, true));
firstPrinted = true;
} else {
sb.append("[super init]");
}
sb.append(")) {\n");
for (int i = firstPrinted ? 1 : 0; i < statements.size(); i++) {
sb.append(generateStatement(statements.get(i), false, true));
}
sb.append("}\nreturn self;\n}");
methodBody = sb.toString();
}
return super.constructorDeclaration(m) + " " + reindent(methodBody) + "\n\n";
}
private String enumConstructorDeclaration(MethodDeclaration m, List<Statement> statements,
IMethodBinding binding) {
assert !statements.isEmpty();
// Append enum generated parameters to invocation. The
// InitializationNormalizer should have fixed this constructor so the
// first statement is a constructor or super invocation.
Statement s = statements.get(0);
assert s instanceof ConstructorInvocation || s instanceof SuperConstructorInvocation;
String invocation = generateStatement(statements.get(0), false, true) + ";\n";
List<?> args = s instanceof ConstructorInvocation
? ((ConstructorInvocation) s).arguments() : ((SuperConstructorInvocation) s).arguments();
String impliedArgs = (args.isEmpty() ? "W" : " w") + "ithNSString:name withInt:ordinal";
int index = invocation.lastIndexOf(']');
invocation = invocation.substring(0, index) + impliedArgs + ']';
StringBuffer sb = new StringBuffer();
if (statements.size() == 1) {
sb.append("{\nreturn ");
sb.append(invocation);
sb.append(";\n}");
} else {
sb.append("{\nif ((self = ");
sb.append(invocation);
sb.append(")) {\n");
for (int i = 1; i < statements.size(); i++) {
sb.append(generateStatement(statements.get(i), false, true));
}
sb.append("}\nreturn self;\n}");
}
String result = super.constructorDeclaration(m) + " " + reindent(sb.toString()) + "\n\n";
return result;
}
@Override
protected void printStaticConstructorDeclaration(MethodDeclaration m) {
String className =
NameTable.javaTypeToObjC(Types.getMethodBinding(m).getDeclaringClass(), false);
StringBuffer sb = new StringBuffer();
sb.append("{\nif (self == [" + className + " class]) {\n");
@SuppressWarnings("unchecked")
List<Statement> statements = m.getBody().statements();
for (Statement statement : statements) {
sb.append(generateStatement(statement, false, true));
}
sb.append("}\n}");
print("+ (void)initialize " + reindent(sb.toString()) + "\n\n");
}
private String generateStatement(Statement stmt, boolean asFunction, boolean inConstructor) {
return StatementGenerator.generate(stmt, fieldHiders, asFunction,
getBuilder().getCurrentLine());
}
private String generateStatement(Statement stmt, boolean asFunction) {
return StatementGenerator.generate(stmt, fieldHiders, asFunction,
getBuilder().getCurrentLine());
}
private String generateExpression(Expression expr) {
return StatementGenerator.generate(expr, fieldHiders, false, getBuilder().getCurrentLine());
}
private void printMainMethod(MethodDeclaration m, String typeName,
List<IMethodBinding> testMethods) {
if (m != null) { // True for unit tests.
Types.addFunction(Types.getMethodBinding(m));
}
println("int main( int argc, const char *argv[] ) {");
if (m != null && (m.getModifiers() & Modifier.NATIVE) > 0) {
println(extractNativeMethodBody(m));
return;
}
indent();
if (Options.useReferenceCounting()) {
printIndent();
println("NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];");
}
if (m != null) {
@SuppressWarnings("unchecked")
List<SingleVariableDeclaration> params = m.parameters();
assert params.size() == 1; // Previously checked in isMainMethod().
printIndent();
printf("IOSObjectArray *%s = JreEmulationMainArguments(argc, argv);\n\n",
params.get(0).getName().getIdentifier());
printMethodBody(m, true);
}
if (testMethods != null) {
printIndent();
printf("int exitCode = [JUnitRunner runTests:[%s class]", typeName);
for (IMethodBinding test : testMethods) {
printf(", @\"%s\"", test.getName());
}
println(", nil];");
} else {
printIndent();
println("int exitCode = 0;");
}
if (Options.useReferenceCounting()) {
print('\n');
printIndent();
println("[pool release];");
}
printIndent();
println("return exitCode;");
unindent();
println("}");
}
private void printMethodBody(MethodDeclaration m, boolean isFunction) throws AssertionError {
for (Object stmt : m.getBody().statements()) {
if (stmt instanceof Statement) {
String objcStmt = reindent(generateStatement((Statement) stmt, isFunction));
println(objcStmt);
} else {
throw new AssertionError("unexpected AST type: " + stmt.getClass());
}
}
}
private String extractNativeMethodBody(MethodDeclaration m) {
assert (m.getModifiers() & Modifier.NATIVE) > 0;
String nativeCode = extractNativeCode(m.getStartPosition(), m.getLength());
if (nativeCode == null) {
J2ObjC.error(m, "no native code found");
return "ERROR";
}
indent();
String code = reindent('{' + nativeCode + '}');
unindent();
return code;
}
private void printImports(CompilationUnit node) {
ImplementationImportCollector collector = new ImplementationImportCollector();
collector.collect(node, getSourceFileName());
Set<ImportCollector.Import> imports = collector.getImports();
if (!imports.isEmpty()) {
Set<String> importStmts = Sets.newTreeSet();
for (ImportCollector.Import imp : imports) {
importStmts.add(String.format("#include \"%s.h\"", imp.getImportFileName()));
}
for (String stmt : importStmts) {
println(stmt);
}
newline();
}
}
private void printStaticVars(List<FieldDeclaration> fields) {
boolean hadStaticVar = false;
for (FieldDeclaration f : fields) {
if (Modifier.isStatic(f.getModifiers())) {
@SuppressWarnings("unchecked")
List<VariableDeclarationFragment> fragments = f.fragments(); // safe by specification
for (VariableDeclarationFragment var : fragments) {
IVariableBinding binding = Types.getVariableBinding(var);
if (!Types.isPrimitiveConstant(binding)) {
String name = NameTable.getName(binding);
Expression initializer = var.getInitializer();
if (initializer != null) {
printConstant(name, initializer);
} else {
printf("static %s %s;\n", NameTable.javaRefToObjC(f.getType()), name);
}
hadStaticVar = true;
}
}
}
}
if (hadStaticVar) {
newline();
}
}
private void printProperties(FieldDeclaration[] fields) {
int nPrinted = 0;
for (FieldDeclaration field : fields) {
if ((field.getModifiers() & Modifier.STATIC) == 0) {
@SuppressWarnings("unchecked")
List<VariableDeclarationFragment> vars = field.fragments(); // safe by definition
for (VariableDeclarationFragment var : vars) {
if (var.getName().getIdentifier().startsWith("this$") && superDefinesVariable(var)) {
// Don't print, as it shadows an inner field in a super class.
continue;
}
String name = NameTable.getName(var.getName());
ITypeBinding type = Types.getTypeBinding(field.getType());
String typeString = NameTable.javaRefToObjC(type);
if (!typeString.endsWith("*")) {
typeString += " ";
}
// Don't emit the getter when there is already a method with the
// same name.
// TODO(user,user): Update when getters are merged with property
// accessors (see issues).
boolean noGetter = false;
ITypeBinding declaringClass = Types.getTypeBinding(field.getParent());
if (declaringClass != null) {
IMethodBinding[] methods = declaringClass.getDeclaredMethods();
for (IMethodBinding method : methods) {
if (method.getName().equals(name) && method.getParameterTypes().length == 0) {
noGetter = true;
break;
}
}
}
String objCFieldName = NameTable.javaFieldToObjC(name);
// Getter
if (!noGetter) {
printf(String.format("- (%s)%s {\n return %s;\n}\n\n",
typeString.trim(), name, objCFieldName));
}
// Setter
printf(String.format("- (void)set%s:(%s)new%s {\n",
NameTable.capitalize(name), typeString.trim(), NameTable.capitalize(name)));
if (type.isPrimitive()) {
printf(String.format(" %s = new%s;\n}\n\n",
objCFieldName, NameTable.capitalize(name)));
} else if (Options.useReferenceCounting() &&
!Types.isWeakReference(Types.getVariableBinding(var))) {
String retentionMethod = type.isEqualTo(Types.getNSString()) ? "copy" : "retain";
printf(String.format(" [%s autorelease];\n %s = [new%s %s];\n}\n\n",
objCFieldName, objCFieldName, NameTable.capitalize(name), retentionMethod));
} else {
printf(String.format(" %s = new%s;\n}\n\n",
objCFieldName, NameTable.capitalize(name)));
}
nPrinted++;
}
}
}
if (nPrinted > 0) {
newline();
}
}
private void printConstant(String name, Expression initializer) {
Object constant = initializer.resolveConstantExpressionValue();
String text = generateExpression(initializer);
// non-constant initializers were already moved to static blocks
assert constant != null;
print("static ");
if (constant instanceof String) {
printf("NSString * %s = %s;\n", name, text);
} else if (constant instanceof Boolean) {
printf("BOOL %s = %s;\n;", name, ((Boolean) constant).booleanValue() ? "YES" : "NO");
} else if (constant instanceof Character) {
printf("unichar %s = %s;\n", name, text);
} else {
assert constant instanceof Number;
Number number = (Number) constant;
if (constant instanceof Byte) {
printf("char %s = %d;\n", name, number.byteValue());
} else if (constant instanceof Double) {
printf("double %s = %s;\n", name, text);
} else if (constant instanceof Float) {
printf("float %s = %s;\n", name, text);
} else if (constant instanceof Integer) {
printf("int %s = %s;\n", name, text);
} else if (constant instanceof Long) {
printf("long long %s = %s;\n", name, text);
} else {
printf("short %s = %d;\n", name, number.shortValue());
}
}
}
/**
* If type extends java.lang.Number, add a required implementation of
* NSValue.objCType(). This can't be implemented as a native method
* because its return type is const char *. Since this method overrides
* the default implementation, the signatures need to match exactly.
*/
private void printObjCTypeMethod(TypeDeclaration node) {
ITypeBinding type = Types.getTypeBinding(node);
if (Types.isJavaNumberType(type)) {
char objCType;
String s = type.getName();
// Strings as case values would be nice here.
if (s.equals("Byte")) {
objCType = 'c';
} else if (s.equals("Double")) {
objCType = 'd';
} else if (s.equals("Float")) {
objCType = 'f';
} else if (s.equals("Integer")) {
objCType = 'i';
} else if (s.equals("Long")) {
objCType = 'q';
} else if (s.equals("Short")) {
objCType = 's';
} else {
return; // Other numeric types will be returned as objects.
}
println("- (const char *)objCType {");
printf(" return \"%c\";\n", objCType);
println("}\n");
}
}
}

View file

@ -14,17 +14,16 @@ import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import com.google.common.collect.Lists;
import com.google.devtools.j2cpp.util.NameTableCpp;
import com.google.devtools.j2objc.util.NameTable;
import com.google.devtools.j2objc.gen.SourceFileGenerator;
import com.google.devtools.j2objc.types.IOSMethod;
import com.google.devtools.j2objc.types.IOSParameter;
import com.google.devtools.j2objc.types.Types;
import com.google.devtools.j2objc.util.NameTable;
public abstract class CppSourceFileGenerator extends SourceFileGenerator {

View file

@ -49,7 +49,7 @@ public class NameTableCpp {
}
if (javaName.equals("byte")) {
// TODO change to appropriate type
return "signed short";
return "wchar_t";
}
if (javaName.equals("char")) {
return "wchar_t";
@ -58,7 +58,7 @@ public class NameTableCpp {
return "signed short";
}
if (javaName.equals("long")) {
return "signed long";
return "long long";
}
if (javaName.equals("float")) {
return "float";