Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Type Resolution #91

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

ctrimble
Copy link
Contributor

@ctrimble ctrimble commented Jan 18, 2017

NOTE: This PR is not complete, but the test suite is passing. Looking for feedback. Also, it is based on #90, so that should be merged before this PR, or this PR should be rebased.

This PR aims to rework type resolution in BridJ, so that resolution code is off loaded to a third party library and to support more complex generics in classes extending StructObject. Once merged, the following struct will work with BridJ:

  public static abstract class AbstractStructField<S extends StructObject, T extends AbstractStructField<S, T>> extends StructObject {
    @Field(0)
    public S getStruct() {
      return io.getNativeObjectField(this, 0);
    }
    
    public T setStruct( S struct ) {
      io.setNativeObjectField(this, 0, struct);
      return (T)this;
    }
  }
  
  public static class StructOfInteger extends StructObject {
    @Field(0)
    public int getField() {
      return io.getIntField(this, 0);
    }
    
    public StructOfInteger setField( int field ) {
      io.setIntField(this, 0, field);
      return this;
    }
  }
  
  // this is the struct that will now work as expected.
  public static class NestedStructOfInteger
    extends AbstractStructField<StructOfInteger, NestedStructOfInteger> {}

Status: Code to support generic resolution has been introduced and a test called StructGenericsTest has been added to verify that structures of this type now work.

TODO: Remove dead code dealing directly with Java's type classes.

Build Changes:

  • The library supporting type resolution, ClassMate, is compiled for Java 1.6, so Java 1.5 compatibility has been abandoned.
  • The source version has been moved to 1.8 and Retrolambda has been introduced, to produce classes compatible with Java 6.
  • The version has been bumped to 0.8.0-SNAPSHOT, to reflect the changes in the resulting artifacts.

Fixes #59

<target>${maven.compiler.target}</target>
<testSource>${maven.compiler.testSource}</testSource>
<testTarget>${maven.compiler.testTarget}</testTarget>
</configuration>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parent pom should not be setting these to 1.5. Instead, it should define these properties to 1.5, allowing child poms to override them, without having to redefine the plugin.

class StructFieldDeclaration {

final StructFieldDescription desc = new StructFieldDescription();
Method setter;
ResolvedMember resolvedSetter;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type should be ResolvedMethod. Also, it would greatly simplify the code base if this was a final field, and it was some type of Consumer<?>. Not sure about performance impact with that.

@@ -58,6 +76,7 @@ public String toString() {
return desc.name + " (index = " + index + (unionWith < 0 ? "" : ", unionWith = " + unionWith) + ", desc = " + desc + ")";
}

@Deprecated
protected static boolean acceptFieldGetter(Member member, boolean getter) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this, dead code.

protected static List<StructFieldDeclaration> listFields(Class<?> structClass) {
List<StructFieldDeclaration> list = new ArrayList<StructFieldDeclaration>();
for (Method method : structClass.getMethods()) {
if (acceptFieldGetter(method, true)) {
StructFieldDeclaration io = fromGetter(method);
try {
// this only works when the names are equal, does not support setXXX methods.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test to show that this is broken and fix it.

@@ -110,7 +143,123 @@ protected static boolean acceptFieldGetter(Member member, boolean getter) {

return list;
}

protected static List<StructFieldDeclaration> listFields2(Class<?> structClass) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get this into a separate class, it does not belong here.

}

protected static ResolvedTypeWithMembers resolveType( Class<?> structClass ) {
TypeResolver resolver = new TypeResolver();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should just be one of these.

TypeResolver resolver = new TypeResolver();
ResolvedType classType = resolver.resolve(structClass);
MemberResolver mr = new MemberResolver(resolver);
mr.setMethodFilter(new Filter<RawMethod>() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make lambda

!method.isStatic();
}
});
mr.setFieldFilter(new Filter<RawField>() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make lambda

decl.desc.isSizeT = member.get(org.bridj.ann.Ptr.class) != null;
}

@Deprecated
protected static StructFieldDeclaration fromField(java.lang.reflect.Field getter) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code, remove

return field;
}

@Deprecated
protected static StructFieldDeclaration fromGetter(Method getter) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code, remove.

return field;
}

@Deprecated
private static StructFieldDeclaration fromMember(Member member) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code, remove.

return mr.resolve(classType, annConfig, null);
}

protected static <T extends Member> void updateDecl(StructFieldDeclaration decl, ResolvedMember<T> member ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this dead code? There is another version below.

ResolvedType rt = (ResolvedType)tpe;
// TODO: what do we do here?
ret = tpe;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this actually be anything other than ResolvedType now?

field.desc.nativeTypeOrPointerTargetType = tpe;
}
}
else if(field.desc.valueType instanceof ParameterizedType) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be dead code.

@@ -227,7 +227,7 @@ static String describe(Type t) {

@SuppressWarnings("deprecation")
protected static void computeStructLayout(StructDescription desc, StructCustomizer customizer) {
List<StructFieldDeclaration> fieldDecls = StructFieldDeclaration.listFields(desc.structClass);
List<StructFieldDeclaration> fieldDecls = StructFieldDeclaration.listFields2(desc.structClass);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix this name after removing original implementation.

@Test
public void testPointerTo_${prim.Name}_Values() {
// Test pointerToInts(int...)
Pointer<${prim.rawTypeRef}> p = Pointer.pointerTo${prim.CapName}s(${prim.value($v1)}, ${prim.value($v2)}, ${prim.value($v3)});
Pointer<${rawTypeRef}> p = Pointer.pointerTo${prim.CapName}s(${prim.value($v1)}, ${prim.value($v2)}, ${prim.value($v3)});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes here fix generic usage and are not changes to functionality.

@@ -699,7 +704,7 @@ public void testUpdateDirectBufferOnNonBufferBoundPointer() {
}
@Test
public void testPointerTo_${prim.Name}_Value() {
Pointer<${prim.rawTypeRef}> p = Pointer.pointerTo${prim.CapName}(${prim.value($v1)});
Pointer<${rawTypeRef}> p = Pointer.pointerTo${prim.CapName}(${prim.value($v1)});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes here fix generic usage and are not changes to functionality.

@ctrimble
Copy link
Contributor Author

I scanned the code base for ParameterizedType and attempted to remove it. There is still a lot of resolution code happening in CRuntime and its subclasses. I would like to remove ParameterizedType, TypeVariable, etc from the codebase, to make sure resolution is consistent, but it may need to happen over several PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant