fornever / avaloniarider Goto Github PK
View Code? Open in Web Editor NEWJetBrains Rider plugin for Avalonia development
License: MIT License
JetBrains Rider plugin for Avalonia development
License: MIT License
Avalonia designer should sends the frames over the BSON protocol. Now it's time to retrieve them and show in the frontend process.
Users should be able to build the plugin on Linux, Windows and macOS, and CI should check the build on these OSs.
Log:
C:\Users\SKProCH\Downloads\AvaloniaRider>gradlew buildPlugin
Starting a Gradle Daemon, 1 incompatible and 1 stopped Daemons could not be reused, use --status for details
> Task :rdgen
Reading hash from build\rdgen\rider\.rdgen
Hashes are different at key 'file: C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar', oldHash: , newHash:2020-02-10_13:22:50.188
Temporary folder created: C:\Users\SKProCH\AppData\Local\Temp\rdgen-17510054252182648603
Searching for Kotlin compiler
Compiling sources from 'C:\Users\SKProCH\Downloads\AvaloniaRider\protocol\src\main\kotlin\model\rider' to 'C:\Users\SKProCH\AppData\Local\Temp\rdgen-17510054252182648603'
User classpath: 'C:\Users\SKProCH\Downloads\AvaloniaRider\build\riderRD-2019.3.1\lib\rd\rider-model.jar'
Rdgen default classpath: 'C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.50\bf65725d4ae2cf00010d84e945fcbc201f590e11\kotlin-stdlib-jdk8-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler\1.3.50\ec5559072cc613b67b47ae33c4936fe00a6e356f\kotlin-compiler-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.50\50ad05ea1c2595fb31b800e76db464d08d599af3\kotlin-stdlib-jdk7-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-jvm\1.3.61\b9311f022363534f8776e4392aa9c4f4d5a62a44\kotlin-scripting-jvm-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-common\1.3.61\169747d90a1ccdd30b25c381a06bee3fe579bf2\kotlin-scripting-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.3.61\c35c0833d5a1e3d229359758482c480306724618\kotlin-compiler-embeddable-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.3.61\2e07c9a84c9e118efb70eede7e579fd663932122\kotlin-reflect-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.61\4702105e97f7396ae41b113fdbdc180ec1eb1e36\kotlin-stdlib-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.61\65abb71d5afb850b68be03987b08e2c864ca3110\kotlin-stdlib-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-script-runtime\1.3.61\e5feb39c8de63dcbdc1154b34ca4413874231605\kotlin-script-runtime-1.3.61.jar'
Resulting kotlinc classpath: 'C:\Users\SKProCH\Downloads\AvaloniaRider\build\riderRD-2019.3.1\lib\rd\rider-model.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.50\bf65725d4ae2cf00010d84e945fcbc201f590e11\kotlin-stdlib-jdk8-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler\1.3.50\ec5559072cc613b67b47ae33c4936fe00a6e356f\kotlin-compiler-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.50\50ad05ea1c2595fb31b800e76db464d08d599af3\kotlin-stdlib-jdk7-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-jvm\1.3.61\b9311f022363534f8776e4392aa9c4f4d5a62a44\kotlin-scripting-jvm-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-common\1.3.61\169747d90a1ccdd30b25c381a06bee3fe579bf2\kotlin-scripting-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.3.61\c35c0833d5a1e3d229359758482c480306724618\kotlin-compiler-embeddable-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.3.61\2e07c9a84c9e118efb70eede7e579fd663932122\kotlin-reflect-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.61\4702105e97f7396ae41b113fdbdc180ec1eb1e36\kotlin-stdlib-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.61\65abb71d5afb850b68be03987b08e2c864ca3110\kotlin-stdlib-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-script-runtime\1.3.61\e5feb39c8de63dcbdc1154b34ca4413874231605\kotlin-script-runtime-1.3.61.jar'
kotlinc -cp C:\Users\SKProCH\Downloads\AvaloniaRider\build\riderRD-2019.3.1\lib\rd\rider-model.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.50\bf65725d4ae2cf00010d84e945fcbc201f590e11\kotlin-stdlib-jdk8-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler\1.3.50\ec5559072cc613b67b47ae33c4936fe00a6e356f\kotlin-compiler-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.50\50ad05ea1c2595fb31b800e76db464d08d599af3\kotlin-stdlib-jdk7-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-jvm\1.3.61\b9311f022363534f8776e4392aa9c4f4d5a62a44\kotlin-scripting-jvm-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-common\1.3.61\169747d90a1ccdd30b25c381a06bee3fe579bf2\kotlin-scripting-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.3.61\c35c0833d5a1e3d229359758482c480306724618\kotlin-compiler-embeddable-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.3.61\2e07c9a84c9e118efb70eede7e579fd663932122\kotlin-reflect-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.61\4702105e97f7396ae41b113fdbdc180ec1eb1e36\kotlin-stdlib-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.61\65abb71d5afb850b68be03987b08e2c864ca3110\kotlin-stdlib-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-script-runtime\1.3.61\e5feb39c8de63dcbdc1154b34ca4413874231605\kotlin-script-runtime-1.3.61.jar -d C:\Users\SKProCH\AppData\Local\Temp\rdgen-17510054252182648603 -jvm-target 1.8 C:\Users\SKProCH\Downloads\AvaloniaRider\protocol\src\main\kotlin\model\rider
warning: unable to find kotlin-stdlib.jar in the Kotlin home directory. Pass either '-no-stdlib' to prevent adding it to the classpath, or the correct '-kotlin-home'
warning: unable to find kotlin-script-runtime.jar in the Kotlin home directory. Pass either '-no-stdlib' to prevent adding it to the classpath, or the correct '-kotlin-home'
warning: unable to find kotlin-reflect.jar in the Kotlin home directory. Pass either '-no-reflect' or '-no-stdlib' to prevent adding it to the classpath, or the correct '-kotlin-home'
Compilation finished in 10734 ms
Loading compiled classes from 'file:/C:/Users/SKProCH/AppData/Local/Temp/rdgen-17510054252182648603/, file:/C:/Users/SKProCH/Downloads/AvaloniaRider/build/riderRD-2019.3.1/lib/rd/rider-model.jar'
RdGen model generator started
Searching classes with namespace prefixes: 'model.rider'
Regex for filtering generators: '.*'
Found 2 gradle generators
3 classes found
1 toplevel class found
Toplevels to generate:
singleton `AvaloniaRiderModel` :> concrete_class `Solution` :> singleton `SolutionModel` :> root `IdeRoot`
Collecting generators (filtering generator's `javaClass.simpleName` by regex '.*'):
0 hardcoded generator(s) -- specified directly in 'Root' constructor
2 gradle generator(s) -- specified in gradle's rdgen plugin 'rdgen { generator { ...} }' sections
0 external generator(s) -- specified by extending kotlin object from class GenerationUnit
++ MATCHED TO ++ 'root `IdeRoot`' + Kotlin11(AsIs, "com.jetbrains.rider.model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\rider\main\kotlin\avaloniarider\model')
++ MATCHED TO ++ 'root `IdeRoot`' + CSharp50(Reversed, "JetBrains.Rider.Model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\dotnet\AvaloniaRider.Plugin\Rider\Model')
After filtering 2 generator(s) to run
Invoke CSharp50(Reversed, "JetBrains.Rider.Model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\dotnet\AvaloniaRider.Plugin\Rider\Model') on root `IdeRoot`, clearFolder=false
Invoke Kotlin11(AsIs, "com.jetbrains.rider.model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\rider\main\kotlin\avaloniarider\model') on root `IdeRoot`, clearFolder=false
Generation finished in 1048 ms
Storing hash into 'build\rdgen\rider\.rdgen'
> Task :rdgen FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':rdgen'.
> java.io.FileNotFoundException: build\rdgen\rider\.rdgen (╤шёЄхьх эх єфрхЄё эрщЄш єърчрээ√щ яєЄ№)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.1.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD FAILED in 6m 34s
1 actionable task: 1 executed```
Currently, when rendering a preview, we rely on AssemblyName.deps.json
and AssemblyName.runtimeconfig.json
being available for the assembly containing the XAML file in question. These files aren't available for non-runnable assemblies in .NET Core, so the preview won't work.
For controls in such assemblies, we should provide a runnable project selector: filter only the runnable projects that depend on the current assembly, and preselect one of them by default.
If no such project exists, then we won't be able to show a preview.
Currently, when the previewer session terminates, an error message may be written to the log. This isn't right; we should consider graceful termination as normal.
Newer Gradle versions allow to use Kotlin instead of Groovy which should dramatically improve the painful build scripting experience. I think we should consider upgrading the build script.
Note to myself: raise an issue about hidpi support
Originally posted by @ForNeVeR in https://github.com/ForNeVeR/AvaloniaRider/pull/7/files
See this code:
See also // TODO[#9]: Update the image size for the renderer
Notes (by @ForNeVeR):
publishPlugin.ps1
scriptRight now, StartAvaloniaPreviewerAction
is a god-file, because it includes all sorts of stuff, from GUI / terminal management to connection management.
Extract the stuff to a proper host and stop holding everything in an action file.
Don't forget to implement Disposable
and shut off the socket connections on component dispose.
The plugin should be able to find the designer and start it.
Hello
Is this possible to have a preview of XAML code in Rider from this plugin?
And if yes, how to to this?
We should add a switcher (like the one Rider have for Windows Forms, or markdown-navigator has for the Markdown files) that will allow the user to switch between source/preview, or even view them both simultaneously.
As many people who want to build the plugin don't usually do JVM development, we could benefit from automated JVM installation using the gradle-jvm-wrapper.
I still investigate if it will work well for all of our users, and want to make its usage optional (but enabled by default). We'll see about that.
Currently, the previewer won't allow the user to scroll big preview images. We need to add scrolling.
Sometimes, when editing a simple XAML document, preview loads a black square instead of some frames. Closer inspection shows that it seemingly receives this black square from an Avalonia previewer process. Further investigation is required.
Also, check if the web previewer has the same problem.
Hello!
It seems to me that it will be more convenient if the frame is located in the center
Would it be possible to add support for Rider 2020.2?
Would it be possible to make rider understand the non-standard XAML syntax that Avalonia uses? For example the control binding syntax that uses a #number sign for referencing other controls. Or the dollar sign.
Are there any plans to implement this, or is it outside the scope of this project?
These file types are ordinary XAML but with another extension, .paml
for Perspex compatibility, and .axaml
for better VS interop (.paml
is supported from Avalonia 0.3, and .axaml
is likely to be included soon).
We should support both of them, too.
Here's a new plan that should help us to produce a more light implementation in terms of code:
Currently, we already support the basic BSON rendering (bitmaps passed via BSON), and there're plans to add HTTP/WebView-based renderer, see #14.
I've decided to abstract these methods and support both of them (since HTTP support seems to not be merged yet into Avalonia main code base).
If the web previewer is enabled, then we should add the Browse button somewhere into the preview editor UI, so the user could view/debug the session in their browser.
We should pass mouse (and keyboard?) user interactions across the Avalonia Remote Protocol.
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaAppTemplate.Namespace.NewUserControl">
Welcome to Avalonia!
</UserControl>
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaAppTemplate.Namespace.NewWindow"
Title="AvaloniaAppTemplate">
Welcome to Avalonia!
</Window>
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style Selector="Window">
<Setter Property="Background" Value="#FF303030"/>
</Style>
</Styles>
avalonia has no template for styles, but it's very useful
Currently, any XAML file will be counted as eligible for XAML Preview. It shouldn't be the case: we need to check XAML flavor of the current project to detect whether the file could be shown in the previewer or not.
See this code:
See this project.
In 2020.2, JavaFX gets unbundled from the IntelliJ platform. So, to properly utilize the web view in the plugin, we'll need to depend on JavaFX Runtime for Plugins.
Since JavaFX is being obsoleted as an IntelliJ component, and JCEF, on the other hand, being included into it by default, we'll have to migrate from JavaFX to JCEF for the plugin version targeting Rider 2020.2+.
TODO:
plugin.xml
build.gradle
This plugin should have some integration tests.
Task :compileDotNet FAILED
FAILURE: Build failed with an exception.
A problem occurred starting process 'command 'powershell''
Expected result: the assembly should be rebvuils successfully, the previewer should reconnect (?)
Actual result: the assembly cannot be rebuilt due to "Cannot copy assembly" error (because it is locked by the previewer process)
Right now it's in a wrong one.
Avalonia suggests to mark XAML files in the project as <AvaloniaResource>
. Currently, XAML support is disabled in such project items. It should be enabled.
Note for implementors: override XamlProjectFileLanguageService.GetPsiLanguageType
to return XamlLanguage.Instance
in cases when projectFile.Properties.GetBuildActions().Any(ba => ba.[IsAvaloniaResource])
. Please contact me in case you, the implementor, is not me.
Possibly only Linux is affected by this issue.
To make the plugin more approachable for .NET developers, I've decided that we have to move most of the logic to the backend. Frontend part should only handle the logic we completely cannot control on the backend.
Currently, if the markup has any errors reported by the preview process, nothing happens.
We should handle the errors received from the previewer, and show them in the previewer tab in the editor.
Also, previewer status (connecting/ready/terminated) should be shown, too.
Let's also allow to restart the previewer in case it was terminated (the same as our Windows Forms designer currently allows).
See this code:
AvaloniaRider/src/rider/main/kotlin/previewer/AvaloniaPreviewerSession.kt
Lines 106 to 108 in 255c8a7
Note for myself: raise an issue about removing this hardcoded content.
Originally posted by @ForNeVeR in https://github.com/ForNeVeR/AvaloniaRider/pull/7/files
Seems like we aren't using one anyway?
There's an Avalonia tool window that's used to host the logs from the previewer process. I don't think it's of use for ordinary users. Let's drop it, and show the stderr/stdout in the IDE log instead.
Current approach to the image rendering in the BSON renderer is rather suboptimal:
BufferedImage
instance per each frameThis needs to be redesigned with more performant and proper approach. See these pieces of code:
AvaloniaRider/src/rider/main/kotlin/previewer/Graphics.kt
Lines 9 to 16 in d620d4c
AvaloniaRider/src/rider/main/kotlin/previewer/Graphics.kt
Lines 18 to 30 in d620d4c
Currently, our CI includes an artifact named distribution.zip
, which, in turn, contains a file avaloniarider-1.3.3.7.zip
.
I think we could improve this workflow by providing a direct upload of avaloniarider-1.3.3.7.zip
. upload-artifact@v2 should support this.
Previewer window should automatically update on source changes.
Right now, it doesn't do that, and for some reason it gets cleared on file save and/or window resize.
I believe this was working and got broken in subsequent updates, so it's just a but that should be fixed.
We should add templates for various Avalonia-related entities:
These entities should generate <AvaloniaResource>
item in the project file. (not sure it's possible to do with Rider's file template mechanism right now, but I'm sure we could invent a clever workaround)
Currently the caches on macOS are too big to be uploaded, but they really shouldn't be that huge (several GiB each). Need to investigate.
Plugin code base should be localizable, thus all the hardcoded user-readable text should be extracted into resource bundles.
To test, add this style:
<Window.Styles>
<Style Selector="Canvas">
<Style.Animations>
<Animation Duration="0:0:1"
Easing="QuadraticEaseInOut"
IterationCount="Infinite">
<KeyFrame Cue="50%">
<Setter Property="ScaleTransform.ScaleX" Value="0.8"/>
<Setter Property="ScaleTransform.ScaleY" Value="0.8"/>
<Setter Property="RotateTransform.Angle" Value="150"/>
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</Window.Styles>
and apply to any XAML element.
While web previewer draws this animation nicely, AvaloniaRemote one gives about 5 FPS.
Probably caused by #40.
Currently, in scope of #17, I'm planning to reuse IDEA-based two-panel previewer, which is very primitive. It doesn't allow to separate editor and previewer by a horizontal separator, only vertical one is available.
We should enable horizontal separator, make it default and configurable.
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.