From 0962203d18664ae119dcff3b0eaac2444bbdbd5a Mon Sep 17 00:00:00 2001 From: Ellizio Date: Sun, 17 Mar 2024 14:34:36 +0300 Subject: [PATCH 1/4] downgrade to net6 --- .../src/main/kotlin/model/rider/ProtocolModel.kt | 14 ++++++++++++++ src/dotnet/Directory.Build.props | 1 + .../ReSharperPlugin.ODataCliUi.Tests.csproj | 2 -- .../ReSharperPlugin.ODataCliUi.Rider.csproj | 1 - 4 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 protocol/src/main/kotlin/model/rider/ProtocolModel.kt diff --git a/protocol/src/main/kotlin/model/rider/ProtocolModel.kt b/protocol/src/main/kotlin/model/rider/ProtocolModel.kt new file mode 100644 index 0000000..4c309ca --- /dev/null +++ b/protocol/src/main/kotlin/model/rider/ProtocolModel.kt @@ -0,0 +1,14 @@ +package model.rider + +import com.jetbrains.rd.generator.nova.Ext +import com.jetbrains.rd.generator.nova.PredefinedType +import com.jetbrains.rd.generator.nova.call +import com.jetbrains.rd.generator.nova.property +import com.jetbrains.rider.model.nova.ide.SolutionModel + +object ProtocolModel : Ext(SolutionModel.Solution) { + init { + property("cliVersion", PredefinedType.string) + call("getCliVersion", PredefinedType.void, PredefinedType.string) + } +} \ No newline at end of file diff --git a/src/dotnet/Directory.Build.props b/src/dotnet/Directory.Build.props index 11eecb1..be5cbba 100644 --- a/src/dotnet/Directory.Build.props +++ b/src/dotnet/Directory.Build.props @@ -1,6 +1,7 @@ + net6.0 Latest MSB3277 true diff --git a/src/dotnet/ReSharperPlugin.ODataCliUi.Tests/ReSharperPlugin.ODataCliUi.Tests.csproj b/src/dotnet/ReSharperPlugin.ODataCliUi.Tests/ReSharperPlugin.ODataCliUi.Tests.csproj index e9553e9..0bd4a4a 100644 --- a/src/dotnet/ReSharperPlugin.ODataCliUi.Tests/ReSharperPlugin.ODataCliUi.Tests.csproj +++ b/src/dotnet/ReSharperPlugin.ODataCliUi.Tests/ReSharperPlugin.ODataCliUi.Tests.csproj @@ -1,7 +1,6 @@ - net8.0 false @@ -10,7 +9,6 @@ - diff --git a/src/dotnet/ReSharperPlugin.ODataCliUi/ReSharperPlugin.ODataCliUi.Rider.csproj b/src/dotnet/ReSharperPlugin.ODataCliUi/ReSharperPlugin.ODataCliUi.Rider.csproj index 11d4dd0..f16d427 100644 --- a/src/dotnet/ReSharperPlugin.ODataCliUi/ReSharperPlugin.ODataCliUi.Rider.csproj +++ b/src/dotnet/ReSharperPlugin.ODataCliUi/ReSharperPlugin.ODataCliUi.Rider.csproj @@ -1,7 +1,6 @@  - net8.0 ReSharperPlugin.ODataCliUi $(AssemblyName) false From 45cede0b26e936d37b43ec921e2917fc8053cf5a Mon Sep 17 00:00:00 2001 From: Ellizio Date: Sun, 17 Mar 2024 20:35:21 +0300 Subject: [PATCH 2/4] implemented dialog model --- .gitignore | 3 + .../ReSharperPlugin.ODataCliUi/Constants.cs | 6 ++ .../ReSharperPlugin.ODataCliUi/PluginHost.cs | 57 +++++++++++++++++++ .../ReSharperPlugin.ODataCliUi/Tracker.cs | 36 ++++++++++++ .../ReSharperPlugin.ODataCliUi/ZoneMarker.cs | 6 ++ .../plugins/odatacliui/MutableProperty.kt | 13 +++++ .../{ => actions}/OpenCliDialogAction.kt | 18 +++++- .../odatacliui/{ => dialogs}/CliDialog.kt | 20 ++++++- .../odatacliui/models/CliDialogModel.kt | 21 +++++++ src/rider/main/resources/META-INF/plugin.xml | 2 +- 10 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 src/dotnet/ReSharperPlugin.ODataCliUi/Constants.cs create mode 100644 src/dotnet/ReSharperPlugin.ODataCliUi/PluginHost.cs create mode 100644 src/dotnet/ReSharperPlugin.ODataCliUi/Tracker.cs create mode 100644 src/dotnet/ReSharperPlugin.ODataCliUi/ZoneMarker.cs create mode 100644 src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/MutableProperty.kt rename src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/{ => actions}/OpenCliDialogAction.kt (57%) rename src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/{ => dialogs}/CliDialog.kt (84%) create mode 100644 src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt diff --git a/.gitignore b/.gitignore index e05792a..55c8536 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ output .gradle .tmp +# Generated files +**/*.Generated.* + # User-specific files *.suo *.user diff --git a/src/dotnet/ReSharperPlugin.ODataCliUi/Constants.cs b/src/dotnet/ReSharperPlugin.ODataCliUi/Constants.cs new file mode 100644 index 0000000..ab802a0 --- /dev/null +++ b/src/dotnet/ReSharperPlugin.ODataCliUi/Constants.cs @@ -0,0 +1,6 @@ +namespace ReSharperPlugin.ODataCliUi; + +public static class Constants +{ + public const string ODataCliPackageId = "microsoft.odata.cli"; +} \ No newline at end of file diff --git a/src/dotnet/ReSharperPlugin.ODataCliUi/PluginHost.cs b/src/dotnet/ReSharperPlugin.ODataCliUi/PluginHost.cs new file mode 100644 index 0000000..34ed7f3 --- /dev/null +++ b/src/dotnet/ReSharperPlugin.ODataCliUi/PluginHost.cs @@ -0,0 +1,57 @@ +using JetBrains.Core; +using JetBrains.Lifetimes; +using JetBrains.ProjectModel; +using JetBrains.ProjectModel.NuGet.DotNetTools; +using JetBrains.Rd.Tasks; +using JetBrains.ReSharper.Feature.Services.Protocol; +using JetBrains.Rider.Model; +using System; +using System.Linq; + +namespace ReSharperPlugin.ODataCliUi; + +[SolutionComponent] +public sealed class PluginHost : IDisposable +{ + private readonly Tracker _tracker; + private readonly ProtocolModel _protocolModel; + + public PluginHost(ISolution solution, Tracker tracker) + { + _protocolModel = solution.GetProtocolSolution().GetProtocolModel(); + _protocolModel.GetCliVersion.SetSync(GetCliVersion); + + _tracker = tracker; + tracker.DotNetToolCacheChanged += OnDotNetToolCacheChanged; + tracker.Start(); + } + + private string GetCliVersion(Lifetime lifetime, Unit unit) => _protocolModel.CliVersion.Value; + + private void OnDotNetToolCacheChanged(DotNetToolCache cache) + { + var localTool = cache.ToolLocalCache.GetAllLocalTools().FirstOrDefault(t => t.PackageId == Constants.ODataCliPackageId); + if (localTool is not null) + { + _protocolModel.CliVersion.Value = $"Local, {localTool.Version}"; + return; + } + + var globalTool = cache.ToolGlobalCache.GetGlobalTool(Constants.ODataCliPackageId)?.FirstOrDefault(); + if (globalTool is not null) + { + _protocolModel.CliVersion.Value = $"Global, {globalTool.Version}"; + return; + } + + _protocolModel.CliVersion.Value = "Not installed"; + } + + public void Dispose() + { + if (_tracker is not null) + { + _tracker.DotNetToolCacheChanged -= OnDotNetToolCacheChanged; + } + } +} \ No newline at end of file diff --git a/src/dotnet/ReSharperPlugin.ODataCliUi/Tracker.cs b/src/dotnet/ReSharperPlugin.ODataCliUi/Tracker.cs new file mode 100644 index 0000000..d48d0c8 --- /dev/null +++ b/src/dotnet/ReSharperPlugin.ODataCliUi/Tracker.cs @@ -0,0 +1,36 @@ +using JetBrains.Lifetimes; +using JetBrains.ProjectModel; +using JetBrains.ProjectModel.NuGet.DotNetTools; +using JetBrains.Threading; +using System; + +namespace ReSharperPlugin.ODataCliUi; + +[SolutionComponent] +public class Tracker +{ + private readonly JetFastSemiReenterableRWLock _lock = new(); + private readonly Lifetime _lifetime; + private readonly SolutionDotnetToolsTracker _dotnetToolsTracker; + + public event Action DotNetToolCacheChanged; + + public Tracker(Lifetime lifetime, SolutionDotnetToolsTracker dotnetToolsTracker) + { + _lifetime = lifetime; + _dotnetToolsTracker = dotnetToolsTracker; + } + + public void Start() + { + _dotnetToolsTracker.DotNetToolCache.Change.Advise(_lifetime, args => + { + if (!args.HasNew || args.New is null) + return; + + using var _ = _lock.UsingWriteLock(); + var cache = args.New; + DotNetToolCacheChanged?.Invoke(cache); + }); + } +} \ No newline at end of file diff --git a/src/dotnet/ReSharperPlugin.ODataCliUi/ZoneMarker.cs b/src/dotnet/ReSharperPlugin.ODataCliUi/ZoneMarker.cs new file mode 100644 index 0000000..caefcc4 --- /dev/null +++ b/src/dotnet/ReSharperPlugin.ODataCliUi/ZoneMarker.cs @@ -0,0 +1,6 @@ +using JetBrains.Application.BuildScript.Application.Zones; + +namespace ReSharperPlugin.ODataCliUi; + +[ZoneMarker] +public class ZoneMarker; \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/MutableProperty.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/MutableProperty.kt new file mode 100644 index 0000000..3b4c61a --- /dev/null +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/MutableProperty.kt @@ -0,0 +1,13 @@ +package com.jetbrains.rider.plugins.odatacliui + +import com.intellij.ui.dsl.builder.MutableProperty + +class MutableProperty(defaultValue: T) : MutableProperty { + private var internalValue = defaultValue + + override fun get(): T = internalValue + + override fun set(value: T) { + internalValue = value + } +} \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/OpenCliDialogAction.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/actions/OpenCliDialogAction.kt similarity index 57% rename from src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/OpenCliDialogAction.kt rename to src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/actions/OpenCliDialogAction.kt index e6fc3e2..38e0483 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/OpenCliDialogAction.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/actions/OpenCliDialogAction.kt @@ -1,19 +1,28 @@ -package com.jetbrains.rider.plugins.odatacliui +package com.jetbrains.rider.plugins.odatacliui.actions import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.project.Project import com.intellij.openapi.rd.util.launchOnUi import com.intellij.openapi.rd.util.lifetime +import com.jetbrains.rd.ide.model.protocolModel +import com.jetbrains.rider.plugins.odatacliui.dialogs.CliDialog import com.jetbrains.rider.plugins.odatacliui.extensions.entityForAction +import com.jetbrains.rider.plugins.odatacliui.models.CliDialogModel +import com.jetbrains.rider.projectView.solution import com.jetbrains.rider.projectView.workspace.isProject import com.jetbrains.rider.projectView.workspace.isWebReferenceFolder class OpenCliDialogAction : AnAction() { override fun actionPerformed(e: AnActionEvent) { val project = e.project ?: return + + val cliVersion = getCliVersion(project) + val dialogModel = CliDialogModel(cliVersion) + project.lifetime.launchOnUi { - val dialog = CliDialog() + val dialog = CliDialog(dialogModel) dialog.show() } } @@ -24,4 +33,9 @@ class OpenCliDialogAction : AnAction() { val entity = e.entityForAction e.presentation.isVisible = entity.isWebReferenceFolder() || entity.isProject() } + + private fun getCliVersion(project: Project): String { + return project.solution.protocolModel.cliVersion.valueOrNull + ?: project.solution.protocolModel.getCliVersion.sync(Unit) + } } \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/CliDialog.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/dialogs/CliDialog.kt similarity index 84% rename from src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/CliDialog.kt rename to src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/dialogs/CliDialog.kt index 5f17953..3490443 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/CliDialog.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/dialogs/CliDialog.kt @@ -1,14 +1,15 @@ -package com.jetbrains.rider.plugins.odatacliui +package com.jetbrains.rider.plugins.odatacliui.dialogs import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.DialogPanel import com.intellij.ui.components.JBTabbedPane import com.intellij.ui.dsl.builder.* +import com.jetbrains.rider.plugins.odatacliui.models.CliDialogModel import javax.swing.JComponent @Suppress("UnstableApiUsage") -class CliDialog : DialogWrapper(false) { +class CliDialog(private val model: CliDialogModel) : DialogWrapper(false) { init { title = "OData Cli UI" init() @@ -23,18 +24,20 @@ class CliDialog : DialogWrapper(false) { return panel { row { - label("Global, 1.2.0") + label(model.cliVersion) .label("OData Cli Version:") .comment("Not installed? Follow instruction") }.bottomGap(BottomGap.MEDIUM) row("Service name:") { textField() .align(AlignX.FILL) + .bindText(model.serviceName) } row("Metadata source:") { textFieldWithBrowseButton(fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFileDescriptor("xml")) .align(AlignX.FILL) .comment("The URI of the metadata document. The value must be set to a valid service document URI or a local file path", Int.MAX_VALUE) + .bindText(model.metadataSource) }.bottomGap(BottomGap.SMALL) row { cell(tabbedPane) @@ -50,46 +53,55 @@ class CliDialog : DialogWrapper(false) { textField() .align(AlignX.FILL) .comment("The name of the generated file. If not provided, then the default name 'Reference.cs' is used", Int.MAX_VALUE) + .bindText(model.fileName) } row("--namespace-prefix") { textField() .align(AlignX.FILL) .comment("The namespace of the client code generated. Example: NorthWindService.Client or it could be a name related to the OData endpoint that you are generating code for", Int.MAX_VALUE) + .bindText(model.namespacePrefix) } row("--excluded-operation-imports") { textField() .align(AlignX.FILL) .comment("Comma-separated list of the names of operation imports to exclude from the generated code. Example: ExcludedOperationImport1, ExcludedOperationImport2", Int.MAX_VALUE) + .bindText(model.excludedOperationImports) } row("--excluded-bound-operations") { textField() .align(AlignX.FILL) .comment("Comma-separated list of the names of bound operations to exclude from the generated code. Example: BoundOperation1, BoundOperation2", Int.MAX_VALUE) + .bindText(model.excludedBoundOperations) } row("--excluded-schema-types") { textField() .align(AlignX.FILL) .comment("Comma-separated list of the names of entity types to exclude from the generated code. Example: EntityType1, EntityType2, EntityType3", Int.MAX_VALUE) + .bindText(model.excludedSchemaTypes) } row { checkBox("--internal") .align(AlignX.FILL) .comment("Applies the internal class modifier on generated classes instead of public thereby making them invisible outside the assembly", Int.MAX_VALUE) + .bindSelected(model.internal) } row { checkBox("--multiple-files") .align(AlignX.FILL) .comment("Split the generated classes into separate files instead of generating all the code in a single file", Int.MAX_VALUE) + .bindSelected(model.multipleFiles) } row { checkBox("--ignore-unexpected-elements") .align(AlignX.FILL) .comment("This flag indicates whether to ignore unexpected elements and attributes in the metadata document and generate the client code if any", Int.MAX_VALUE) + .bindSelected(model.ignoreUnexpectedElements) } row { checkBox("--upper-camel-case") .align(AlignX.FILL) .comment("Transforms names (class and property names) to upper camel-case so that to better conform with C# naming conventions", Int.MAX_VALUE) + .bindSelected(model.upperCamelCase) } } @@ -98,11 +110,13 @@ class CliDialog : DialogWrapper(false) { textField() .align(AlignX.FILL) .comment("Headers that will get sent along with the request when fetching the metadata document from the service. Format: Header1:HeaderValue, Header2:HeaderValue", Int.MAX_VALUE) + .bindText(model.customHeaders) } row("--proxy") { textField() .align(AlignX.FILL) .comment("Proxy settings. Format: domain\\\\user:password@SERVER:PORT", Int.MAX_VALUE) + .bindText(model.proxy) } } } \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt new file mode 100644 index 0000000..ec9b4fd --- /dev/null +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt @@ -0,0 +1,21 @@ +package com.jetbrains.rider.plugins.odatacliui.models + +import com.jetbrains.rider.plugins.odatacliui.MutableProperty + +class CliDialogModel(val cliVersion: String) { + val serviceName = MutableProperty("") + val metadataSource = MutableProperty("") + + val fileName = MutableProperty("") + val namespacePrefix = MutableProperty("") + val excludedOperationImports = MutableProperty("") + val excludedBoundOperations = MutableProperty("") + val excludedSchemaTypes = MutableProperty("") + val internal = MutableProperty(false) + val multipleFiles = MutableProperty(false) + val ignoreUnexpectedElements = MutableProperty(false) + val upperCamelCase = MutableProperty(true) + + val customHeaders = MutableProperty("") + val proxy = MutableProperty("") +} \ No newline at end of file diff --git a/src/rider/main/resources/META-INF/plugin.xml b/src/rider/main/resources/META-INF/plugin.xml index 8677c57..ec19690 100644 --- a/src/rider/main/resources/META-INF/plugin.xml +++ b/src/rider/main/resources/META-INF/plugin.xml @@ -13,7 +13,7 @@ - + From 1c032c8017b0dab57c7606ab3b02f4a2aade1110 Mon Sep 17 00:00:00 2001 From: Ellizio Date: Sun, 17 Mar 2024 21:32:05 +0300 Subject: [PATCH 3/4] fix build --- build.gradle | 1 + .../jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt | 2 -- .../rider/plugins/odatacliui/{ => models}/MutableProperty.kt | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) rename src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/{ => models}/MutableProperty.kt (83%) diff --git a/build.gradle b/build.gradle index bf96210..ab4664b 100644 --- a/build.gradle +++ b/build.gradle @@ -74,6 +74,7 @@ task setBuildTool { } task compileDotNet { + dependsOn rdgen dependsOn setBuildTool doLast { def arguments = setBuildTool.args.clone() diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt index ec9b4fd..a256165 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/CliDialogModel.kt @@ -1,7 +1,5 @@ package com.jetbrains.rider.plugins.odatacliui.models -import com.jetbrains.rider.plugins.odatacliui.MutableProperty - class CliDialogModel(val cliVersion: String) { val serviceName = MutableProperty("") val metadataSource = MutableProperty("") diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/MutableProperty.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/MutableProperty.kt similarity index 83% rename from src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/MutableProperty.kt rename to src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/MutableProperty.kt index 3b4c61a..fec5f7e 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/MutableProperty.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/odatacliui/models/MutableProperty.kt @@ -1,4 +1,4 @@ -package com.jetbrains.rider.plugins.odatacliui +package com.jetbrains.rider.plugins.odatacliui.models import com.intellij.ui.dsl.builder.MutableProperty From c9622fd7741e7a1137615442dfac4ec46021092b Mon Sep 17 00:00:00 2001 From: Ellizio Date: Sun, 17 Mar 2024 22:12:29 +0300 Subject: [PATCH 4/4] try to fix build --- .github/workflows/CI.yml | 2 ++ build.gradle | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a5de554..6497156 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,6 +17,7 @@ jobs: ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-Build-${{ hashFiles('gradlew.bat', 'src/dotnet/*/*.csproj', 'src/dotnet/*.props', 'gradle-wrapper.properties') }} + - run: ./gradlew :rdgen --no-daemon - run: ./gradlew :buildPlugin --no-daemon - uses: actions/upload-artifact@v3 if: always() @@ -38,4 +39,5 @@ jobs: ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-Test-${{ hashFiles('gradlew.bat', 'src/dotnet/*/*.csproj', 'src/dotnet/*.props', 'gradle-wrapper.properties') }} + - run: ./gradlew :rdgen --no-daemon - run: ./gradlew :testDotNet --no-daemon diff --git a/build.gradle b/build.gradle index ab4664b..bf96210 100644 --- a/build.gradle +++ b/build.gradle @@ -74,7 +74,6 @@ task setBuildTool { } task compileDotNet { - dependsOn rdgen dependsOn setBuildTool doLast { def arguments = setBuildTool.args.clone()