Skip to content

Commit

Permalink
Moves thrown exception types data into the class metadata.
Browse files Browse the repository at this point in the history
	Change on 2013/11/14 by kstanger <kstanger@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=56659474
  • Loading branch information
tomball committed Nov 21, 2013
1 parent b4e9d40 commit 8ecc6c5
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 151 deletions.
11 changes: 5 additions & 6 deletions jre_emul/Classes/IOSClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#import "IOSProtocolClass.h"
#import "IOSShortArray.h"
#import "JavaMetadata.h"
#import "objc/message.h"
#import "objc/runtime.h"

@implementation IOSClass
Expand Down Expand Up @@ -594,12 +595,10 @@ - (IOSObjectArray *)getDeclaredAnnotations {
- (JavaClassMetadata *)getMetadata {
Class cls = [self objcClass];
if (cls) {
SEL sel = @selector(__metadata);
if ([cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
J2ObjcClassInfo *rawData = (ARCBRIDGE J2ObjcClassInfo *) [cls performSelector:sel];
#pragma clang diagnostic pop
// Can't use respondsToSelector here because that will search superclasses.
Method metadataMethod = JreFindClassMethod(cls, "__metadata");
if (metadataMethod) {
J2ObjcClassInfo *rawData = (ARCBRIDGE J2ObjcClassInfo *) method_invoke(cls, metadataMethod);
return AUTORELEASE([[JavaClassMetadata alloc] initWithMetadata:rawData]);
}
}
Expand Down
39 changes: 11 additions & 28 deletions jre_emul/Classes/IOSConcreteClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//

#import "IOSConcreteClass.h"
#import "IOSReflection.h"
#import "JavaMetadata.h"
#import "java/lang/ClassCastException.h"
#import "java/lang/Enum.h"
Expand Down Expand Up @@ -201,32 +202,15 @@ - (IOSObjectArray *)getConstructors {
return getConstructorsImpl(self, YES);
}

static SEL FindSelector(NSString *name, Class cls) {
unsigned int count;
SEL result = nil;
Method *methods = class_copyMethodList(cls, &count);
for (NSUInteger i = 0; i < count; i++) {
SEL sel = method_getName(methods[i]);
if ([name isEqualToString:NSStringFromSelector(sel)]) {
result = sel;
break;
}
}
free(methods);
return result;
}

- (JavaLangReflectMethod *)findMethodWithTranslatedName:(NSString *)objcName {
SEL selector = FindSelector(objcName, class_);
if (selector) {
JavaClassMetadata *metadata = [self getMetadata];
return [JavaLangReflectMethod methodWithSelector:selector withClass:self
withMetadata:metadata ? [metadata findMethodInfo:objcName] : nil];
const char *name = [objcName UTF8String];
Method method = JreFindInstanceMethod(class_, name);
if (!method) {
method = JreFindClassMethod(class_, name);
}
selector = FindSelector(objcName, object_getClass(class_));
if (selector) {
if (method) {
JavaClassMetadata *metadata = [self getMetadata];
return [JavaLangReflectMethod methodWithSelector:selector withClass:self
return [JavaLangReflectMethod methodWithSelector:method_getName(method) withClass:self
withMetadata:metadata ? [metadata findMethodInfo:objcName] : nil];
}
return nil;
Expand All @@ -235,12 +219,11 @@ - (JavaLangReflectMethod *)findMethodWithTranslatedName:(NSString *)objcName {
static JavaLangReflectConstructor *GetConstructorImpl(
IOSConcreteClass *iosClass, IOSObjectArray *paramTypes) {
NSString *name = IOSClass_GetTranslatedMethodName(@"init", paramTypes);
SEL selector = FindSelector(name, iosClass->class_);
if (selector) {
NSString *objcName = NSStringFromSelector(selector);
Method method = JreFindInstanceMethod(iosClass->class_, [name UTF8String]);
if (method) {
JavaClassMetadata *metadata = [iosClass getMetadata];
return [JavaLangReflectConstructor constructorWithSelector:selector withClass:iosClass
withMetadata:metadata ? [metadata findMethodInfo:objcName] : nil];
return [JavaLangReflectConstructor constructorWithSelector:method_getName(method)
withClass:iosClass withMetadata:metadata ? [metadata findMethodInfo:name] : nil];
}
@throw AUTORELEASE([[JavaLangNoSuchMethodException alloc] init]);
}
Expand Down
4 changes: 4 additions & 0 deletions jre_emul/Classes/IOSReflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define JreEmulation_IOSReflection_h

#import <Foundation/Foundation.h>
#import "objc/runtime.h"

@protocol JavaLangReflectType;

Expand Down Expand Up @@ -94,6 +95,7 @@ typedef struct J2ObjcMethodInfo {
const char *javaName;
const char *returnType;
uint16_t modifiers;
const char *exceptions;
} J2ObjcMethodInfo;

typedef struct J2ObjcClassInfo {
Expand Down Expand Up @@ -135,5 +137,7 @@ typedef union {
} J2ObjcRawValue;

extern id<JavaLangReflectType> JreTypeForString(const char *typeStr);
extern Method JreFindInstanceMethod(Class cls, const char *name);
extern Method JreFindClassMethod(Class cls, const char *name);

#endif // JreEmulation_IOSReflection_h
19 changes: 18 additions & 1 deletion jre_emul/Classes/IOSReflection.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

#import "IOSReflection.h"

#import <Foundation/Foundation.h>
#import "IOSClass.h"
#import "java/lang/AssertionError.h"
#import "java/lang/reflect/TypeVariableImpl.h"
Expand All @@ -41,3 +40,21 @@
NSString *msg = [NSString stringWithFormat:@"invalid type from metadata %s", typeStr];
@throw AUTORELEASE([[JavaLangAssertionError alloc] initWithNSString:msg]);
}

Method JreFindInstanceMethod(Class cls, const char *name) {
unsigned int count;
Method result = nil;
Method *methods = class_copyMethodList(cls, &count);
for (NSUInteger i = 0; i < count; i++) {
if (strcmp(name, sel_getName(method_getName(methods[i]))) == 0) {
result = methods[i];
break;
}
}
free(methods);
return result;
}

Method JreFindClassMethod(Class cls, const char *name) {
return JreFindInstanceMethod(object_getClass(cls), name);
}
1 change: 0 additions & 1 deletion jre_emul/Classes/java/lang/reflect/ExecutableMember.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@
// Protected methods.
- (NSString *)internalName;
- (JavaLangReflectMethod *)getAnnotationsAccessor:(NSString *)methodName;
- (JavaLangReflectMethod *)getExceptionsAccessor:(NSString *)methodName;
- (JavaLangReflectMethod *)getParameterAnnotationsAccessor:(NSString *)methodName;

@end
Expand Down
18 changes: 10 additions & 8 deletions jre_emul/Classes/java/lang/reflect/ExecutableMember.m
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,16 @@ - (BOOL)isSynthetic {
}

- (IOSObjectArray *)getExceptionTypes {
JavaLangReflectMethod *method = [self getExceptionsAccessor:[self internalName]];
if (method) {
IOSObjectArray *noArgs = [IOSObjectArray arrayWithLength:0 type:[NSObject getClass]];
return (IOSObjectArray *) [method invokeWithId:nil withNSObjectArray:noArgs];
if (metadata_ && metadata_->exceptions) {
NSString *exceptionsStr = [NSString stringWithUTF8String:metadata_->exceptions];
NSArray *exceptionsArray = [exceptionsStr componentsSeparatedByString:@";"];
IOSObjectArray *result =
[IOSObjectArray arrayWithLength:[exceptionsArray count] type:[IOSClass getClass]];
NSUInteger count = 0;
for (NSString *thrownException in exceptionsArray) {
IOSObjectArray_Set(result, count++, [IOSClass classForIosName:thrownException]);
}
return result;
} else {
return [IOSObjectArray arrayWithLength:0 type:[IOSClass getClass]];
}
Expand Down Expand Up @@ -230,10 +236,6 @@ - (JavaLangReflectMethod *)getAnnotationsAccessor:(NSString *)methodName {
return getAccessor(class_, methodName, @"annotations");
}

- (JavaLangReflectMethod *)getExceptionsAccessor:(NSString *)methodName {
return getAccessor(class_, methodName, @"exceptions");
}

- (JavaLangReflectMethod *)getParameterAnnotationsAccessor:(NSString *)methodName {
return [self getAnnotationsAccessor:[NSString stringWithFormat:@"%@_params", methodName]];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,16 +354,21 @@ public void test_getComponentType() {
*/
public void test_getConstructor$Ljava_lang_Class()
throws NoSuchMethodException {
assertNotNull(TestClass.class.getConstructor(new Class[0]));
assertNotNull(TestClass.class.getConstructor(Object.class));
TestClass.class.getConstructor(new Class[0]);
try {
TestClass.class.getConstructor(Object.class);
fail("Found private constructor");
} catch (NoSuchMethodException e) {
// Correct - constructor with obj is private
}
}

/**
* @tests java.lang.Class#getConstructors()
*/
public void test_getConstructors() throws Exception {
Constructor<?>[] c = TestClass.class.getConstructors();
assertEquals("Incorrect number of constructors returned", 2, c.length);
assertEquals("Incorrect number of constructors returned", 1, c.length);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public class MetadataGenerator {
private final AbstractTypeDeclaration typeNode;
private final ITypeBinding type;
private boolean generated = false;
private boolean hasMetadata = false;
private int methodMetadataCount = 0;

public MetadataGenerator(AbstractTypeDeclaration typeNode) {
Expand All @@ -49,11 +48,6 @@ public MetadataGenerator(AbstractTypeDeclaration typeNode) {
this.type = Types.getTypeBinding(typeNode);
}

public boolean hasMetadata() {
ensureGenerated();
return hasMetadata;
}

public String getMetadataSource() {
ensureGenerated();
return builder.toString();
Expand All @@ -78,7 +72,6 @@ private void generateMetadata() {
printf("NULL, ");
} else {
printf("\"%s\", ", pkgName);
hasMetadata = true;
}
printf("%s, ", getEnclosingName());
printf("0x%s, ", Integer.toHexString(getTypeModifiers()));
Expand All @@ -95,7 +88,6 @@ private String getEnclosingName() {
if (declaringType == null) {
return "NULL";
}
hasMetadata = true;
StringBuilder sb = new StringBuilder("\"");
List<String> types = Lists.newArrayList();
while (declaringType != null) {
Expand All @@ -118,7 +110,6 @@ private void generateMethodsMetadata() {
String metadata = getMethodMetadata(Types.getMethodBinding(decl));
if (metadata != null) {
methodMetadata.add(metadata);
hasMetadata = true;
}
}
if (methodMetadata.size() > 0) {
Expand All @@ -132,35 +123,53 @@ private void generateMethodsMetadata() {
}

private String getMethodMetadata(IMethodBinding method) {
ITypeBinding[] paramTypes = method.getParameterTypes();
if ((method.isConstructor() && paramTypes.length == 0) || method.isSynthetic()) {
if (method.isSynthetic()) {
return null;
}

// Needs metadata if not a public static or instance method.
int modifiers = getMethodModifiers(method);
boolean needsMetadata = (modifiers & ~Modifier.STATIC) != Modifier.PUBLIC;

String returnTypeStr = "NULL";
String returnTypeStr = null;
if (!method.isConstructor()) {
ITypeBinding returnType = method.getReturnType();
returnTypeStr = String.format("\"%s\"", getTypeName(returnType));
returnTypeStr = getTypeName(returnType);
if (!returnType.isPrimitive() || returnType.getName().equals("boolean")) {
needsMetadata = true;
}
}
String methodName = "NULL";
String methodName = null;
ITypeBinding[] paramTypes = method.getParameterTypes();
// Most of the time the method name can be parsed from the ObjC selector
// but not if the first parameter contains the substring "With".
if (paramTypes.length > 0 && NameTable.parameterKeyword(paramTypes[0]).contains("With")) {
methodName = "\"" + method.getName() + "\"";
methodName = method.getName();
needsMetadata = true;
}
String thrownExceptions = getThrownExceptions(method);
needsMetadata |= thrownExceptions != null;
if (!needsMetadata) {
return null;
}
return String.format(" { \"%s\", %s, %s, 0x%x },\n",
NameTable.getMethodSelector(method), methodName, returnTypeStr, modifiers);
return String.format(" { \"%s\", %s, %s, 0x%x, %s },\n",
NameTable.getMethodSelector(method), cStr(methodName), cStr(returnTypeStr), modifiers,
cStr(thrownExceptions));
}

private String getThrownExceptions(IMethodBinding method) {
ITypeBinding[] exceptionTypes = method.getExceptionTypes();
if (exceptionTypes.length == 0) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < exceptionTypes.length; i++) {
if (i != 0) {
sb.append(';');
}
sb.append(NameTable.getFullName(exceptionTypes[i]));
}
return sb.toString();
}

private int printSuperclassTypeArguments() {
Expand All @@ -172,7 +181,6 @@ private int printSuperclassTypeArguments() {
if (typeArgs.length == 0) {
return 0;
}
hasMetadata = true;
print(" static const char *superclass_type_args[] = {");
for (int i = 0; i < typeArgs.length; i++) {
if (i != 0) {
Expand Down Expand Up @@ -215,7 +223,6 @@ private int getTypeModifiers() {
if (type.isAnonymous()) {
modifiers |= 0x8000;
}
hasMetadata |= (modifiers & ~0x200) != Modifier.PUBLIC;
return modifiers;
}

Expand All @@ -234,15 +241,19 @@ private static int getMethodModifiers(IMethodBinding type) {
return modifiers;
}

public void print(String s) {
private String cStr(String s) {
return s == null ? "NULL" : "\"" + s + "\"";
}

private void print(String s) {
builder.append(s);
}

public void printf(String format, Object... args) {
private void printf(String format, Object... args) {
builder.append(String.format(format, args));
}

public void println(String s) {
private void println(String s) {
builder.append(s).append('\n');
}
}
Loading

0 comments on commit 8ecc6c5

Please sign in to comment.