jeromiya / xamarin.flutter Goto Github PK
View Code? Open in Web Editor NEWThis project forked from adamped/xamarin.flutter
Running Flutter on Xamarin
License: MIT License
This project forked from adamped/xamarin.flutter
Running Flutter on Xamarin
License: MIT License
Currently mixins output as a combination of an interface and a static class with the default mixin method implementations. It should now output C# 8 interfaces with default method implementations.
This may be a long-term project.
If you look here:
https://github.com/JeroMiya/xamarin.flutter/blob/master/FlutterSDK/src/Foundation/Isolates.cs#L299
You'll see the _ComputeImpl
delegate is missing a generic annotation. But other generic delegates seem to work just fine:
https://github.com/JeroMiya/xamarin.flutter/blob/master/FlutterSDK/src/Foundation/Isolates.cs#L298
I did a quick pass for issues in the output towards the beginning of the fork. Now with a few fixes in place, I should do a more comprehensive review pass on the output and create issues that are found.
In Dart you can use void
in place of a generic type argument, but in C# you cannot. This leads to syntax errors in the transpiler output. For example:
https://github.com/JeroMiya/xamarin.flutter/blob/master/FlutterSDK/src/Foundation/Diagnostics.cs#L1683
Create a DartVoid
struct and use in place of void
for generic type references.
Personally I'm not a fan of regions. Add an option to enable region generation in the output (default off).
IMHO in order for this to be successful, you need to continue to transpile the flutter SDK, but instead of re-writing the flutter engine in C# it should bind/pinvoke into the real engine.
For example, see FlutterSDK/Cupertino/Colors.cs
in the generated output, you'll see for example this line:
internal static FlutterSDK.Foundation.Diagnostics.DiagnosticsProperty<Color> CreateCupertinoColorProperty(string name,FlutterBinding.UI.Color value,bool showName = true,@Object defaultValue = default(@Object),FlutterSDK.Foundation.Diagnostics.DiagnosticsTreeStyle style = default(FlutterSDK.Foundation.Diagnostics.DiagnosticsTreeStyle),DiagnosticLevel level = default(DiagnosticLevel)){
throw new NotImplementedException();
}
}
Without doing too deep of a dive into the code, I'm going to guess the generator is prefixing @Object
because it's generated a class called Object
(probably the dart base object class?), in which case it would probably be better to rename this DartObject
and add a type name rewriting rule to make this more clear.
When constructor bodies are generated, they appear to be missing the opening brace.
There are a few places, such as the Foundation folder, where the flutter project has a "web" version of a class and a "native" version. Exclude the web version from the generated output, as any future Flutter.Net for the web is going to be based on WASM, and if there are any differences in implementation needed for .net wasm they will probably be completely unrelated to the Dart ones.
Rather than spend a bunch of time making sure the code generator outputs properly indented and formatted code, just run dotnet format on the output at the end.
Also update the readme with instructions on installing the dotnet-format tool.
Async functions currently get garbled in the transpiled output. Also, yield* <exp>;
statements need to be translated to async foreach(var enumItem in (<exp>)) { yield return enumItem; }
.
dotnet format supports .editorconfig configuration including end of line configuration. Probably should include a decent C# friendly .editorconfig and include the EOL configuration. Then remove the lec
command from run.bat
.
When outputting a yield statement in C#, we need to add return
, as in yield return <exp>
instead of just yield <exp>
.
if (message.Length+startOffset<width){
yield message;
return ;
}
It looks like @brainoffline did some work in their fork that was never merged upstream into @adamped's original repository. Review and merge the changes.
NOTE: not sure what happened after it was forked by @brainoffline but attempting to merge in @adamped's later changes causes all sorts of havok to the git history. Going to have to carefully cherry pick commits manually and make sure they get propper attribution.
While it makes sense to name the directory containing the generated SDK "FlutterSDK", the namespace should just be "Flutter".
Mixins are going to be a tricky feature to implement in the code gen for the following reasons:
It's going to be a long time before the generator is able to support mixins, so for now, hand-port or override the generator output for mixin base classes and use interfaces with default implementations.
Currently I'm aware of some defined in Diagnostics.dart in the Foundation section. There may be more.
I don't think Dart annotations really translate well to C# automatically. Add exclusions to the transpiler for all the annotations in the Flutter framework and hand port these.
I'm seeing some garbled list literals in the transpiler output:
https://github.com/JeroMiya/xamarin.flutter/blob/master/FlutterSDK/src/Foundation/Diagnostics.cs#L761
public new List<FlutterSDK.Foundation.Diagnostics.DiagnosticsNode> DebugDescribeChildren() => new List, <DiagnosticsNode>(};
Looks to be related to instantiating generic types maybe? Or it could be related to method body expressions like => {method body}
.
This should be a high priority bug because the garbled method bodies are breaking {}
pairs in the output causing a number of unrelated syntax errors.
At least temporarily, add the code-gen output to the git repository. It's going to be a while before the code gen is fully functional or stable, and being able to review output diffs and make hand-written overrides may get the project closer to "functioning flutter.net framework" faster that relying 100% on the code-gen to generate correct output.
As part of this: document a convention for implementing hand-written overrides to generated output that allow for more reliable diff review.
Even with method bodies turned on in config, some properties still get transpiled to throw NotImplementedException
, for example:
public virtual int SubtreeDepth { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
public virtual bool IncludeProperties { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
public virtual bool ExpandPropertyValues { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
In sync functions in Dart, you can just return;
without yielding a value to break the function. In C# the equivalent is yield break
.
{
if (message.Length+startOffset<width){
yield message;
return ;
}
Note: Implementing this implies that the code outputting the return
statement can be aware of whether the return statement is within a sync
function or a regular function. That is not currently the case - so part of solving this issue is to pass down the method and/or function context (or some stripped down version of same) into the entity processing functions that need it.
The analyzer currently spits out a console message for each file it converts. However, I'd like to start outputting warnings and such, e.g. for files that are skipped, unsupported Dart syntax, etc... and the current output is too verbose for that to be useful.
For now, just disable the current verbose file conversion messages. If it's useful, we can add them back later as an option.
Dart sync functions are garbled in the generated output because of a badly generated signature:
https://github.com/JeroMiya/xamarin.flutter/blob/master/FlutterSDK/src/Foundation/Diagnostics.cs#L1092-L1094
private Iterable<string> _WordWrapLine(string message, List<int> wrapRanges, int width, int startOffset = 0, int otherLineOffset = 0)
sync
*
{
Looks mostly correct except for the extra "sync *" output before the opening brace.
Currently the transpiler creates a new namespace for each file rather than the directory it's in. Maybe it should be an option, but I think it would be better to just have one namespace per directory.
Example, instead of this:
using FlutterSDK.Widgets.Pages;
using FlutterSDK.Widgets.Performanceoverlay;
using FlutterSDK.Widgets.Automatickeepalive;
using FlutterSDK.Widgets.Scrollcontroller;
using FlutterSDK.Widgets.Widgetinspector;
using FlutterSDK.Widgets.Icon;
using FlutterSDK.Widgets.Scrollcontext;
using FlutterSDK.Widgets.Inheritedmodel;
using FlutterSDK.Widgets.Annotatedregion;
// etc...
Just this:
using FlutterSDK.Widgets;
Of course, this may result in name resolution issues, so close this issue if that happens in the flutter namespace itself (I don't believe it does).
These comments are useful, not just on their own merit, but because they keep the transpiled code closer to the original source which helps with reviewing transpiler correctness.
See if we can add newlines at least to a switch block, or maybe get dotnet format
to be more aggressive and add newlines.
There's currently a workaround implemented which comments out spread elements in list literal initializers. However, the spread operator is used extensively throughout Flutter and it needs to be fully implemented.
I'm going to hazard a guess that we'll want to implement two versions of the list literal processor - one for list literals without spread and one with spread, in case the C# implementation with spread has some runtime overhead that we could avoid if there's no spread operator in a literal.
I think the C# implementation of the spread will be to use a helper function that constructs the list, instead of a new
expression. Something along these lines:
// Original Dart code: return <string>['item 1', ...spreadOperand];
return DartUtils.MakeListWithSpreads<string>(list => {
list.Add('item 1');
foreach(var i in spreadOperand) {
list.Add(i);
}
});
Looks like <summary>
comments were disabled at some point. Try to re-enable them and test the output. See if there are any issues caused and create issues as necessary.
It appears the auto-format-on-save option in vscode is reformatting the code every time a change is made. Rather than fight the setting, just auto format all the code and check it in as one diff so result in lots of diffs every time a change is made to a file that hasn't been formatted.
If you take for instance /animations/animation.dart
you'll see an abstract dart class Animation<T>
. However, the transpiler outputs this as a non-abstract class, and abstract methods are given empty bodies.
This may have been a workaround in the original project for some issue, but if it needs to be reviewed. I'd prefer abstract methods to stay abstract in C#.
Named constructors in dart are actual constructors. While we have to transpile them into static methods in C#, we also have to generate the corresponding constructor. Otherwise, we'll get syntax errors if there is no default constructor or if fields are readonly fields or properties.
The named constructor in Dart should be transpiled into a regular private constructor in C#, followed by a static method representing the named constructor which forwards the parameters to the internal constructor.
All types are nullable in the current version of Dart (though in the future this will not be the case), but value types are not by default in C#. A number of syntax errors in the transpiler output are a result of this difference. For now, let's output all of these types as nullable by default until the analyzer can tell us whether or not any given instance is nullable or not:
https://dart.dev/null-safety
Lots of the dart code uses Dart types like Dictionary<,>
. There are custom subclasses of .net collections with Dart methods added in Globals.cs but in many cases these cause type ambiguity errors in the transpiler output. For example:
Prefix these conflicting types with Dart
, e.g. DartDictionary
so that they don't result in ambiguity errors.
Static references (looks like particularly ones from the dart namespace) are getting garbled by the transpiler. For example:
https://github.com/JeroMiya/xamarin.flutter/blob/master/FlutterSDK/src/Animation/Animationcontroller.cs#L438
else if (target == Value)
{
simulationDuration = Dart:coreDefaultClass.Duration.Zero;
}
Here's the equivalent dart code:
} else if (target == value) {
// Already at target, don't animate.
simulationDuration = Duration.zero;
}
Transpiler is working now with method implementations turned off, but crashes with them turned on.
As an example, see FlutterSDK/Cuptertino/Colors.cs
in the generated output. You'll see this line at the top (the base directory of the path may be different):
using file:///C:/src/xamarin.flutter/flutter/lib/foundation.dart;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.