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

Consider support for extending native generic classes and providing generic arguments #1346

Open
vmutafov opened this issue Apr 8, 2019 · 3 comments

Comments

@vmutafov
Copy link
Contributor

vmutafov commented Apr 8, 2019

Currently, there is no way to implement for example java.util.List<T> and provide information what would be the type T. When extending such class/interface from TypeScript the following way:

@Interfaces([java.util.List])
class JSList implements java.util.List {
}

the static binding generator prior 5.3.1 would generate a proxy class with a similar signature:
public class JSList implements java.util.List
The introduced changes of the SBG in 5.3.1 generate public class JSList implements java.util.List<Object> having resolved the generic parameter T using its erasure (in this case java.lang.Object) as if it's a raw class inheritance.

With the changes of the SBG in 5.3.1, there is a way to feed it information about what would be the generic parameters when extending, however this would require some changes in the syntax of extending/implementing native classes:

@Native
class JSList implements java.util.List<java.lang.Integer>{
}

The above shown syntax would be possible with some changes in the webpack plugin and the js_parser.js in the SBG.
In order to collect information about the generic arguments provided in the TS code there should be a custom transformer plugged into the webpack pipeline whose goal would be to lookup every TS node with a @Native decorator and preserve its extended class and implemented interfaces information somewhere. This could be stored by modifying the AST and creating internal decorators only for storage. Further, when the js_parser.js parses the JS code, it can look for the internal decorators and retrieve the information about the generics storing them for the SBG.

@vmutafov
Copy link
Contributor Author

Additional possibilities: #1355

@vmutafov
Copy link
Contributor Author

vmutafov commented Sep 13, 2019

Changing the native class extend API could also be made to allow generating native methods which are not present in the class being extended. This could be done in this way, for example:

@Native("com.named.NativeList")
class NamedNativeList implements List{

    @NativeMethod
    add(data: string): void {
        throw new Error("Method not implemented.");
    }

}

@Native
class NativeList implements List{

    @NativeField
    data: string;

    nonNativeData: string;

    @NativeMethod
    add(data: string): void {
        throw new Error("Method not implemented.");
    }

    addAt(index: number): void{

    }

    @NativeExternalMethod
    getNativeData: (param1: String, param2: number) => String
}

In this example, fields annotated with @NativeField would be generated in the Java file as regular fields, methods annotated with @NativeMethod would be generated as regular methods and the lambda field annotated with @NativeExternalMethod would be generated as Java native method. Having Java native methods could allow easier use of JNA for accessing C/C++/Rust libraries.

@vmutafov
Copy link
Contributor Author

vmutafov commented Sep 13, 2019

Supporting additional Java/Kotlin annotations to be set on the extending class could be possible, too. If we have for example the Java annotation:

@interface UserDefinedCustomJavaAnnotation {

    String value();

}

and we want to extend java.lang.Object setting the annotation in TypeScript:

@UserDefinedCustomJavaAnnotation({value: "some string data"})
class TSClass extends java.lang.Object{
}

The proposal for the syntax of the Java annotation usage in TypeScript is a little bit strange at first glance. This is because of the object {value: "some string data"}. Implementing the annotation support this way enables quite easy use of default annotation members and enable the user to set only what he needs. In this example, the TS decorator will then be translated by the SBG into @UserDefinedCustomJavaAnnotation(value = "some string data") and appending it to the generated Java mirror class. Of course, if the annotation's members are all marked as default, the user should be able to use the annotation as @UserDefinedCustomJavaAnnotation not needing to provide parameters.

If we want to support Java/Kotlin annotations, we should follow the definition of the annotations in Java. We must guarantee all possible types of annotation members could be used in TS.

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

No branches or pull requests

1 participant