-
Notifications
You must be signed in to change notification settings - Fork 53
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
Containing type does not implement interface #470
Comments
I think this is the same as: |
jpobst
added
bug
Component does not function as intended
generator
Issues binding a Java library (generator, class-parse, etc.)
labels
Apr 6, 2020
jonpryor
pushed a commit
that referenced
this issue
Aug 14, 2020
`generator` is an amazingly powerful tool that has proven to be very versatile over the past decade. However, many of the remaining bugs fall into a category that is hard to fix given `generator`'s current design, which is: 1. Read in Java model 2. Make tweaks to Java model 3. Open `<TYPE>.cs` 4. Loop through Java model determining what C# to write The issue with this is that we are deciding **what** to generate on-the-fly to a write-only stream. This means that once we've written to the stream we cannot change it if future information suggests that we should. A good example is issue #461. The Java model is: #461 Given: // Java: interface AnimatorListener { onAnimationEnd (int p0); onAnimationEnd (int p0, p1); } Looping through this, we see we need to generate an `EventArgs` class for `AnimatorListener.onAnimationEnd(int p0)`, so we do: public partial class OnAnimationEndEventArgs : global::System.EventArgs { int p0; public OnAnimationEndEventArgs (int p0) { this.p0= p0; } public int P0 { get { return p0; } } } Then we get to the second method `AnimatorListener.onAnimationEnd(int p0, int p1)` and see that we need to add additional parameters to `OnAnimationEndEventArgs`. However we cannot modify the already written class, so we generate a second `OnAnimationEndEventArgs` with different parameters, which causes CS0101 compilation errors in C#. Another example is we can generate an empty `InterfaceConsts` class. This is because we write the class opening because we think we have members to place in it (`public static class InterfaceConsts {`), but as we loop through the members we thought we were going to add they all get eliminated. At that point all we can do is close the class with no members. The solution to both examples above is "simple": we need to first loop through the rest of the Java model and determine what we **actually** need to generate before we start writing anything. We can then merge the two `OnAnimationEndEventArgs` classes, or forgo writing an empty `InterfaceConsts` type. However, rather than adding this additional logic in each instance that needs it, there is enough benefit to convert the entire `generator` architecture to work by first building a C# model of what needs to be generated that can be tweaked before writing to a file, resulting in a design of: 1. Read in Java model 2. Make tweaks to Java model 3. ***Build C# model from Java model*** 4. ***Make tweaks to C# model*** 5. Open `<TYPE>.cs` 6. Loop through C# model, writing code Having a C# model to tweak should also help in a few other tricky cases we fail at today, like determining `override`s (#367, #586) and implementing `abstract` methods for `abstract` classes inheriting an `interface` (#470). Additionally, having distinct logic and source writing steps will make unit testing better. Currently, the only way to test the *logic* of if we are going to generate something is to write out the source code and compare it to "expected" source code. This means tiny fixes can have many "expected" files that need to change (#625). With separate steps, we can have a set of unit tests that test what code we are writing, and a set that tests the logic of determining what to generate. To test the above "2 `EventArgs` classes" example, we can test a fix by looking at the created C# model to ensure that only a single combined `OnAnimationEndEventArgs` class is created. We would not need to write out the generated source code and compare it to expected source code. To assist in this new design, add a new `Xamarin.SourceWriter.dll` assembly which is responsible for generating the C# source code. This eliminates a lot of hard to read and error prone code such as: writer.WriteLine ("{0}{1}{2}{3}{4} unsafe {5} {6}{7} ({8})", indent, visibility, static_arg, virt_ov, seal, ret, is_explicit ? GetDeclaringTypeOfExplicitInterfaceMethod (method.OverriddenInterfaceMethod) + '.' : string.Empty, method.AdjustedName, method.GetSignature (opt)); and replaces it with: var m = new MethodWriter { IsPublic = true, IsUnsafe = true, IsOverride = true, Name = method.AdjustedName }; m.Write (…); which will emit: public unsafe override void DoSomething () { } `Xamarin.SourceWriter.CodeWriter` is a wrapper around a `System.IO.Stream` that tracks the current indent level, rather than needing to pass `indent` around to every method. cw.WriteLine ("{"); cw.Indent (); // ... write block body ... cw.Unindent (); cw.WriteLine ("}"); ~~ Testing ~~ Many existing unit tests call directly into methods like `CodeGenerator.WriteProperties()`. These methods are no longer available when using `JavaInterop`/`XAJavaInterop`. These tests were either changed to use `CodeGenerator.WriteType()` or were moved to only run for `XamarinAndroid` codegen target. Tests were updated to ignore whitespace and line endings differences, as the refactor did not preserve 100% identical whitespace.
Related to this: #359 (comment) |
Notes: We are generating:
I think the correct fix is to not generate the explicitly implemented methods in |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have a simple case of abstract classes that aren't generating the correct code.
Java: interface-tests.jar.zip
I create a binding project, but I get some errors:
I can fix this by creating a partial class and adding the interface, but that seems like it should have worked?
The text was updated successfully, but these errors were encountered: