diff --git a/gradle.properties b/gradle.properties index 60c60badef..0da6ca38d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -41,7 +41,7 @@ intellijPluginVersion=1.13.1 # every time you bump rd version: # 1. regenerate all models # 2. check if rider plugin works -rdVersion=2022.2.1 +rdVersion=2022.3.3 # to enable - add -PincludeRiderInBuild=true in build CLI includeRiderInBuild=false jacocoVersion=0.8.8 diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt index 6c6579a42b..c4029c1862 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt @@ -65,10 +65,7 @@ class EngineProcessModel private constructor( fun create(lifetime: Lifetime, protocol: IProtocol): EngineProcessModel { EngineProcessRoot.register(protocol.serializers) - return EngineProcessModel().apply { - identify(protocol.identity, RdId.Null.mix("EngineProcessModel")) - bind(lifetime, protocol, "EngineProcessModel") - } + return EngineProcessModel() } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdInstrumenterAdapter.Generated.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdInstrumenterAdapter.Generated.kt index c9c56ee162..c71e8a80cd 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdInstrumenterAdapter.Generated.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdInstrumenterAdapter.Generated.kt @@ -42,10 +42,7 @@ class RdInstrumenterAdapter private constructor( fun create(lifetime: Lifetime, protocol: IProtocol): RdInstrumenterAdapter { EngineProcessRoot.register(protocol.serializers) - return RdInstrumenterAdapter().apply { - identify(protocol.identity, RdId.Null.mix("RdInstrumenterAdapter")) - bind(lifetime, protocol, "RdInstrumenterAdapter") - } + return RdInstrumenterAdapter() } private val __StringNullableSerializer = FrameworkMarshallers.String.nullable() diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdSourceFindingStrategy.Generated.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdSourceFindingStrategy.Generated.kt index 11324e77f2..86806e0930 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdSourceFindingStrategy.Generated.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/RdSourceFindingStrategy.Generated.kt @@ -44,10 +44,7 @@ class RdSourceFindingStrategy private constructor( fun create(lifetime: Lifetime, protocol: IProtocol): RdSourceFindingStrategy { EngineProcessRoot.register(protocol.serializers) - return RdSourceFindingStrategy().apply { - identify(protocol.identity, RdId.Null.mix("RdSourceFindingStrategy")) - bind(lifetime, protocol, "RdSourceFindingStrategy") - } + return RdSourceFindingStrategy() } private val __StringNullableSerializer = FrameworkMarshallers.String.nullable() diff --git a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/rd/generated/InstrumentedProcessModel.Generated.kt b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/rd/generated/InstrumentedProcessModel.Generated.kt index 6718640e3e..f3cec5feb7 100644 --- a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/rd/generated/InstrumentedProcessModel.Generated.kt +++ b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/rd/generated/InstrumentedProcessModel.Generated.kt @@ -54,10 +54,7 @@ class InstrumentedProcessModel private constructor( fun create(lifetime: Lifetime, protocol: IProtocol): InstrumentedProcessModel { InstrumentedProcessRoot.register(protocol.serializers) - return InstrumentedProcessModel().apply { - identify(protocol.identity, RdId.Null.mix("InstrumentedProcessModel")) - bind(lifetime, protocol, "InstrumentedProcessModel") - } + return InstrumentedProcessModel() } diff --git a/utbot-rd/build.gradle b/utbot-rd/build.gradle index 01ac9574df..be70e3e35e 100644 --- a/utbot-rd/build.gradle +++ b/utbot-rd/build.gradle @@ -1,10 +1,16 @@ plugins { - id 'com.jetbrains.rdgen' version "2022.2.1" + id 'com.jetbrains.rdgen' version "2022.3.3" } import com.jetbrains.rd.generator.gradle.RdGenExtension import com.jetbrains.rd.generator.gradle.RdGenTask +if (includeRiderInBuild.toBoolean()) { + def utbotRider = project.rootProject.childProjects["utbot-rider"] + evaluationDependsOn(utbotRider.path) + tasks.getByName("classes").dependsOn(utbotRider.tasks.getByName("addRiderModelsToUtbotModels")) +} + compileKotlin { kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8 @@ -26,6 +32,8 @@ configurations { lifetimedProcessMockCompileClasspath.extendsFrom configurations.compileClasspath processWithRdServerMockCompileClasspath.extendsFrom configurations.compileClasspath rdgenModelsCompileClasspath.extendsFrom configurations.compileClasspath + if (includeRiderInBuild.toBoolean()) + riderRdgenModelsCompileClasspath.extendsFrom configurations.rdgenModelsCompileClasspath } sourceSets { @@ -44,8 +52,17 @@ sourceSets { srcDirs = ["src/main/rdgen"] } } + if (includeRiderInBuild.toBoolean()) { + riderRdgenModels { + kotlin { + srcDirs = ["src/main/riderRdgenModels"] + } + } + } } +def riderModelJar = new File(project.buildDir, "libs/rider-model.jar") + dependencies { implementation project(':utbot-core') implementation group: 'com.jetbrains.rd', name: 'rd-framework', version: rdVersion @@ -56,6 +73,10 @@ dependencies { processWithRdServerMockImplementation project(':utbot-rd') rdgenModelsCompileClasspath group: 'com.jetbrains.rd', name: 'rd-gen', version: rdVersion + + if (includeRiderInBuild.toBoolean()) { + riderRdgenModelsCompileClasspath files(riderModelJar) + } } task lifetimedProcessMockJar(type: Jar) { @@ -99,6 +120,50 @@ test { systemProperty("PROCESS_WITH_RD_SERVER_MOCK", processWithRdServerMockJar.archiveFile.get().getAsFile().canonicalPath) } +if (includeRiderInBuild.toBoolean()) { + def currentProjectDir = project.projectDir + def riderProject = project.rootProject.childProjects["utbot-rider"] + def riderTask = riderProject.tasks.getByName("addRiderModelsToUtbotModels") + // !!!! IMPORTANT !!!! + // after generation you should MANUALLY correct kotlin generated code as it is incorrectly references some rider model + // mandatory steps: + // 1. In UtBotRiderModel.Generated.kt change package to `package org.utbot.rider.generated` + // 2. then import all unreferenced classes + // otherwise you will have broken plugin initialization and ClassNotFoundException + task generateRiderModels(type: RdGenTask) { + dependsOn(riderTask) + + def riderProjectDir = riderProject.projectDir + def generatedOutputDir = new File(riderProjectDir, "src/main/kotlin/org/utbot/rider/generated") + def hashDir = generatedOutputDir + def sourcesDir = new File(currentProjectDir, "src/main/riderRdgenModels/org/utbot/rider/rd/models") + def rdParams = extensions.getByName("params") as RdGenExtension + + group = "rdgen" + rdParams.verbose = true + rdParams.sources(sourcesDir) + rdParams.hashFolder = hashDir.canonicalPath + rdParams.packages = "org.utbot.rider.rd.models" + rdParams.classpath(riderModelJar) + + rdParams.generator { + language = "kotlin" + transform = "symmetric" + root = "com.jetbrains.rider.model.nova.ide.IdeRoot" + directory = generatedOutputDir.canonicalPath + namespace = "org.utbot.rider.generated" + } + + rdParams.generator { + language = "csharp" + transform = "symmetric" + root = "com.jetbrains.rider.model.nova.ide.IdeRoot" + namespace = "UtBot" + directory = new File(riderProjectDir, "src/dotnet/UtBot/UtBot/Generated") + } + } +} + task generateInstrumentedProcessModels(type: RdGenTask) { def currentProjectDir = project.projectDir def instrumentationProjectDir = project.rootProject.childProjects["utbot-instrumentation"].projectDir diff --git a/utbot-rd/src/main/kotlin/org/utbot/rd/generated/LoggerModel.Generated.kt b/utbot-rd/src/main/kotlin/org/utbot/rd/generated/LoggerModel.Generated.kt index d8f0f59f87..11d81e7768 100644 --- a/utbot-rd/src/main/kotlin/org/utbot/rd/generated/LoggerModel.Generated.kt +++ b/utbot-rd/src/main/kotlin/org/utbot/rd/generated/LoggerModel.Generated.kt @@ -43,10 +43,7 @@ class LoggerModel private constructor( fun create(lifetime: Lifetime, protocol: IProtocol): LoggerModel { LoggerRoot.register(protocol.serializers) - return LoggerModel().apply { - identify(protocol.identity, RdId.Null.mix("LoggerModel")) - bind(lifetime, protocol, "LoggerModel") - } + return LoggerModel() } diff --git a/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SettingsModel.Generated.kt b/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SettingsModel.Generated.kt index f025404818..e9d7f35d4b 100644 --- a/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SettingsModel.Generated.kt +++ b/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SettingsModel.Generated.kt @@ -43,10 +43,7 @@ class SettingsModel private constructor( fun create(lifetime: Lifetime, protocol: IProtocol): SettingsModel { SettingsRoot.register(protocol.serializers) - return SettingsModel().apply { - identify(protocol.identity, RdId.Null.mix("SettingsModel")) - bind(lifetime, protocol, "SettingsModel") - } + return SettingsModel() } diff --git a/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SynchronizationModel.Generated.kt b/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SynchronizationModel.Generated.kt index e520a29383..503f6dd889 100644 --- a/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SynchronizationModel.Generated.kt +++ b/utbot-rd/src/main/kotlin/org/utbot/rd/generated/SynchronizationModel.Generated.kt @@ -44,10 +44,7 @@ class SynchronizationModel private constructor( fun create(lifetime: Lifetime, protocol: IProtocol): SynchronizationModel { SynchronizationRoot.register(protocol.serializers) - return SynchronizationModel().apply { - identify(protocol.identity, RdId.Null.mix("SynchronizationModel")) - bind(lifetime, protocol, "SynchronizationModel") - } + return SynchronizationModel() } diff --git a/utbot-rd/src/main/rdgen/org/utbot/rd/models/CSharpModel.kt b/utbot-rd/src/main/rdgen/org/utbot/rd/models/CSharpModel.kt index 720d49e885..cc75a8ff12 100644 --- a/utbot-rd/src/main/rdgen/org/utbot/rd/models/CSharpModel.kt +++ b/utbot-rd/src/main/rdgen/org/utbot/rd/models/CSharpModel.kt @@ -13,6 +13,11 @@ object VSharpModel: Ext(CSharpRoot) { field("parameters", immutableList(PredefinedType.string)) } + val mapEntry = structdef { + field("key", PredefinedType.string) + field("value", PredefinedType.string) + } + val generateArguments = structdef { field("assemblyPath", PredefinedType.string) field("projectCsprojPath", PredefinedType.string) @@ -20,6 +25,7 @@ object VSharpModel: Ext(CSharpRoot) { field("methods", immutableList(methodDescriptor)) field("generationTimeoutInSeconds", PredefinedType.int) field("targetFramework", PredefinedType.string.nullable) + field("assembliesFullNameToTheirPath", immutableList(mapEntry)) } val generateResults = structdef { diff --git a/utbot-rd/src/main/riderRdgenModels/org/utbot/rider/rd/models/UtBotRiderModel.kt b/utbot-rd/src/main/riderRdgenModels/org/utbot/rider/rd/models/UtBotRiderModel.kt new file mode 100644 index 0000000000..17b6e52ccb --- /dev/null +++ b/utbot-rd/src/main/riderRdgenModels/org/utbot/rider/rd/models/UtBotRiderModel.kt @@ -0,0 +1,25 @@ +@file:Suppress("unused") + +package org.utbot.rider.rd.models + +import com.jetbrains.rd.generator.nova.* +import com.jetbrains.rider.model.nova.ide.SolutionModel + +object UtBotRiderModel : Ext(SolutionModel.Solution) { + val startPublishArgs = structdef { + field("fileName", PredefinedType.string) + field("arguments", PredefinedType.string) + field("workingDirectory", PredefinedType.string) + } + + init { + signal("startPublish", startPublishArgs).async + signal("logPublishOutput", PredefinedType.string).async + signal("logPublishError", PredefinedType.string).async + signal("stopPublish", PredefinedType.int).async + + signal("startVSharp", PredefinedType.void).async + signal("logVSharp", PredefinedType.string).async + signal("stopVSharp", PredefinedType.int).async + } +} \ No newline at end of file diff --git a/utbot-rider/build.gradle.kts b/utbot-rider/build.gradle.kts index 5a27f87b97..728e074838 100644 --- a/utbot-rider/build.gradle.kts +++ b/utbot-rider/build.gradle.kts @@ -9,15 +9,17 @@ plugins { intellij { type.set("RD") - version.set("2023.1-SNAPSHOT") -} - -dependencies { - implementation(group ="com.jetbrains.rd", name = "rd-framework", version = rdVersion) - implementation(group ="com.jetbrains.rd", name = "rd-core", version = rdVersion) + version.set("2022.3.3") } tasks { + register("addRiderModelsToUtbotModels") { + val rdLibDirectory = File(project.tasks.setupDependencies.get().idea.get().classes, "lib/rd/rider-model.jar") + from(rdLibDirectory) + val utbotRd = project.rootProject.childProjects["utbot-rd"]!! + val targetDir = utbotRd.buildDir.resolve("libs") + into(targetDir) + } val dotNetSdkCmdPath = projectDir.resolve("dotnet-sdk.cmd").toString() compileKotlin { @@ -29,7 +31,7 @@ tasks { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } @@ -38,7 +40,7 @@ tasks { } patchPluginXml { - sinceBuild.set("231") + sinceBuild.set("223") version.set(semVer) } diff --git a/utbot-rider/src/dotnet/UtBot/UtBot.Rd/Generated/VSharpModel.Generated.cs b/utbot-rider/src/dotnet/UtBot/UtBot.Rd/Generated/VSharpModel.Generated.cs index 794bd54451..6a7401a126 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot.Rd/Generated/VSharpModel.Generated.cs +++ b/utbot-rider/src/dotnet/UtBot/UtBot.Rd/Generated/VSharpModel.Generated.cs @@ -84,7 +84,7 @@ private VSharpModel ( - protected override long SerializationHash => -7151966238299581951L; + protected override long SerializationHash => 9120359939503061610L; protected override Action Register => RegisterDeclaredTypesSerializers; public static void RegisterDeclaredTypesSerializers(ISerializers serializers) @@ -127,7 +127,7 @@ public override string ToString() /// - ///

Generated from: CSharpModel.kt:16

+ ///

Generated from: CSharpModel.kt:21

///
public sealed class GenerateArguments : IPrintable, IEquatable { @@ -139,6 +139,7 @@ public sealed class GenerateArguments : IPrintable, IEquatable Methods {get; private set;} public int GenerationTimeoutInSeconds {get; private set;} [CanBeNull] public string TargetFramework {get; private set;} + [NotNull] public List AssembliesFullNameToTheirPath {get; private set;} //private fields //primary constructor @@ -148,13 +149,15 @@ public GenerateArguments( [NotNull] string solutionFilePath, [NotNull] List methods, int generationTimeoutInSeconds, - [CanBeNull] string targetFramework + [CanBeNull] string targetFramework, + [NotNull] List assembliesFullNameToTheirPath ) { if (assemblyPath == null) throw new ArgumentNullException("assemblyPath"); if (projectCsprojPath == null) throw new ArgumentNullException("projectCsprojPath"); if (solutionFilePath == null) throw new ArgumentNullException("solutionFilePath"); if (methods == null) throw new ArgumentNullException("methods"); + if (assembliesFullNameToTheirPath == null) throw new ArgumentNullException("assembliesFullNameToTheirPath"); AssemblyPath = assemblyPath; ProjectCsprojPath = projectCsprojPath; @@ -162,10 +165,11 @@ [CanBeNull] string targetFramework Methods = methods; GenerationTimeoutInSeconds = generationTimeoutInSeconds; TargetFramework = targetFramework; + AssembliesFullNameToTheirPath = assembliesFullNameToTheirPath; } //secondary constructor //deconstruct trait - public void Deconstruct([NotNull] out string assemblyPath, [NotNull] out string projectCsprojPath, [NotNull] out string solutionFilePath, [NotNull] out List methods, out int generationTimeoutInSeconds, [CanBeNull] out string targetFramework) + public void Deconstruct([NotNull] out string assemblyPath, [NotNull] out string projectCsprojPath, [NotNull] out string solutionFilePath, [NotNull] out List methods, out int generationTimeoutInSeconds, [CanBeNull] out string targetFramework, [NotNull] out List assembliesFullNameToTheirPath) { assemblyPath = AssemblyPath; projectCsprojPath = ProjectCsprojPath; @@ -173,6 +177,7 @@ public void Deconstruct([NotNull] out string assemblyPath, [NotNull] out string methods = Methods; generationTimeoutInSeconds = GenerationTimeoutInSeconds; targetFramework = TargetFramework; + assembliesFullNameToTheirPath = AssembliesFullNameToTheirPath; } //statics @@ -184,11 +189,13 @@ public void Deconstruct([NotNull] out string assemblyPath, [NotNull] out string var methods = ReadMethodDescriptorList(ctx, reader); var generationTimeoutInSeconds = reader.ReadInt(); var targetFramework = ReadStringNullable(ctx, reader); - var _result = new GenerateArguments(assemblyPath, projectCsprojPath, solutionFilePath, methods, generationTimeoutInSeconds, targetFramework); + var assembliesFullNameToTheirPath = ReadMapEntryList(ctx, reader); + var _result = new GenerateArguments(assemblyPath, projectCsprojPath, solutionFilePath, methods, generationTimeoutInSeconds, targetFramework, assembliesFullNameToTheirPath); return _result; }; public static CtxReadDelegate> ReadMethodDescriptorList = MethodDescriptor.Read.List(); public static CtxReadDelegate ReadStringNullable = JetBrains.Rd.Impl.Serializers.ReadString.NullableClass(); + public static CtxReadDelegate> ReadMapEntryList = MapEntry.Read.List(); public static CtxWriteDelegate Write = (ctx, writer, value) => { @@ -198,9 +205,11 @@ public void Deconstruct([NotNull] out string assemblyPath, [NotNull] out string WriteMethodDescriptorList(ctx, writer, value.Methods); writer.Write(value.GenerationTimeoutInSeconds); WriteStringNullable(ctx, writer, value.TargetFramework); + WriteMapEntryList(ctx, writer, value.AssembliesFullNameToTheirPath); }; public static CtxWriteDelegate> WriteMethodDescriptorList = MethodDescriptor.Write.List(); public static CtxWriteDelegate WriteStringNullable = JetBrains.Rd.Impl.Serializers.WriteString.NullableClass(); + public static CtxWriteDelegate> WriteMapEntryList = MapEntry.Write.List(); //constants @@ -218,7 +227,7 @@ public bool Equals(GenerateArguments other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return AssemblyPath == other.AssemblyPath && ProjectCsprojPath == other.ProjectCsprojPath && SolutionFilePath == other.SolutionFilePath && Methods.SequenceEqual(other.Methods) && GenerationTimeoutInSeconds == other.GenerationTimeoutInSeconds && Equals(TargetFramework, other.TargetFramework); + return AssemblyPath == other.AssemblyPath && ProjectCsprojPath == other.ProjectCsprojPath && SolutionFilePath == other.SolutionFilePath && Methods.SequenceEqual(other.Methods) && GenerationTimeoutInSeconds == other.GenerationTimeoutInSeconds && Equals(TargetFramework, other.TargetFramework) && AssembliesFullNameToTheirPath.SequenceEqual(other.AssembliesFullNameToTheirPath); } //hash code trait public override int GetHashCode() @@ -231,6 +240,7 @@ public override int GetHashCode() hash = hash * 31 + Methods.ContentHashCode(); hash = hash * 31 + GenerationTimeoutInSeconds.GetHashCode(); hash = hash * 31 + (TargetFramework != null ? TargetFramework.GetHashCode() : 0); + hash = hash * 31 + AssembliesFullNameToTheirPath.ContentHashCode(); return hash; } } @@ -245,6 +255,7 @@ public void Print(PrettyPrinter printer) printer.Print("methods = "); Methods.PrintEx(printer); printer.Println(); printer.Print("generationTimeoutInSeconds = "); GenerationTimeoutInSeconds.PrintEx(printer); printer.Println(); printer.Print("targetFramework = "); TargetFramework.PrintEx(printer); printer.Println(); + printer.Print("assembliesFullNameToTheirPath = "); AssembliesFullNameToTheirPath.PrintEx(printer); printer.Println(); } printer.Print(")"); } @@ -259,7 +270,7 @@ public override string ToString() /// - ///

Generated from: CSharpModel.kt:25

+ ///

Generated from: CSharpModel.kt:31

///
public sealed class GenerateResults : IPrintable, IEquatable { @@ -379,6 +390,100 @@ public override string ToString() } + /// + ///

Generated from: CSharpModel.kt:16

+ ///
+ public sealed class MapEntry : IPrintable, IEquatable + { + //fields + //public fields + [NotNull] public string Key {get; private set;} + [NotNull] public string Value {get; private set;} + + //private fields + //primary constructor + public MapEntry( + [NotNull] string key, + [NotNull] string value + ) + { + if (key == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException("value"); + + Key = key; + Value = value; + } + //secondary constructor + //deconstruct trait + public void Deconstruct([NotNull] out string key, [NotNull] out string value) + { + key = Key; + value = Value; + } + //statics + + public static CtxReadDelegate Read = (ctx, reader) => + { + var key = reader.ReadString(); + var value = reader.ReadString(); + var _result = new MapEntry(key, value); + return _result; + }; + + public static CtxWriteDelegate Write = (ctx, writer, value) => + { + writer.Write(value.Key); + writer.Write(value.Value); + }; + + //constants + + //custom body + //methods + //equals trait + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((MapEntry) obj); + } + public bool Equals(MapEntry other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Key == other.Key && Value == other.Value; + } + //hash code trait + public override int GetHashCode() + { + unchecked { + var hash = 0; + hash = hash * 31 + Key.GetHashCode(); + hash = hash * 31 + Value.GetHashCode(); + return hash; + } + } + //pretty print + public void Print(PrettyPrinter printer) + { + printer.Println("MapEntry ("); + using (printer.IndentCookie()) { + printer.Print("key = "); Key.PrintEx(printer); printer.Println(); + printer.Print("value = "); Value.PrintEx(printer); printer.Println(); + } + printer.Print(")"); + } + //toString + public override string ToString() + { + var printer = new SingleLinePrettyPrinter(); + Print(printer); + return printer.ToString(); + } + } + + /// ///

Generated from: CSharpModel.kt:9

///
diff --git a/utbot-rider/src/dotnet/UtBot/UtBot.Rd/UtBot.Rd.csproj b/utbot-rider/src/dotnet/UtBot/UtBot.Rd/UtBot.Rd.csproj index a048c98330..2f89595393 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot.Rd/UtBot.Rd.csproj +++ b/utbot-rider/src/dotnet/UtBot/UtBot.Rd/UtBot.Rd.csproj @@ -7,8 +7,8 @@ - - - + + + diff --git a/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/UtBot.VSharp.csproj b/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/UtBot.VSharp.csproj index 283f061fde..a8cab38432 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/UtBot.VSharp.csproj +++ b/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/UtBot.VSharp.csproj @@ -13,6 +13,6 @@ - + diff --git a/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/VSharpMain.cs b/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/VSharpMain.cs index be62f3b596..662f2e9a1a 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/VSharpMain.cs +++ b/utbot-rider/src/dotnet/UtBot/UtBot.VSharp/VSharpMain.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Loader; using System.Text; using System.Text.Json; +using System.Text.RegularExpressions; using JetBrains.Collections.Viewable; using JetBrains.Lifetimes; using JetBrains.Rd; @@ -43,41 +45,47 @@ public override void WriteLine(string value) public override Encoding Encoding => Encoding.Default; } - private static GenerateResults GenerateImpl(GenerateArguments arguments) + private static GenerateResults GenerateImpl(GenerateArguments arguments, IReadOnlyDictionary assembliesFullNameToTheirPath) { var (assemblyPath, projectCsprojPath, solutionFilePath, - methodDescriptors, generationTimeout, targetFramework) = arguments; + methodDescriptors, generationTimeout, targetFramework, _) = arguments; + + string AssemblyResolveFunc(string fullAssemblyName) + { + return !assembliesFullNameToTheirPath.TryGetValue(fullAssemblyName, out var found) ? null : found; + } var assemblyLoadContext = new AssemblyLoadContext(VSharpProcessName); - assemblyLoadContext.Resolving += (context, name) => + assemblyLoadContext.Resolving += (context, assemblyName) => { - var found = Directory.GetFiles(new FileInfo(assemblyPath).Directory?.FullName, $"{name.Name}.dll") - .FirstOrDefault(); - if (found is null) + var found = AssemblyResolveFunc(assemblyName.FullName); + if (found == null) { return null; } - return context.LoadFromAssemblyPath(found); }; - var assembly = assemblyLoadContext.LoadFromAssemblyPath(assemblyPath); - var methods = methodDescriptors.Select(d => d.ToMethodInfo(assembly)).ToList(); - var declaringType = methods.Select(m => m.DeclaringType).Distinct().SingleOrDefault(); - var stat = TestGenerator.Cover(methods, generationTimeout, verbosity:Verbosity.Info); + using (new DependencyResolver(AssemblyResolveFunc)) + { + var assembly = assemblyLoadContext.LoadFromAssemblyPath(assemblyPath); + var methods = methodDescriptors.Select(d => d.ToMethodInfo(assembly)).ToList(); + var declaringType = methods.Select(m => m.DeclaringType).Distinct().SingleOrDefault(); + var stat = TestGenerator.Cover(methods, generationTimeout, verbosity: Verbosity.Info); - var testedProject = new FileInfo(projectCsprojPath); - var solution = new FileInfo(solutionFilePath); + var testedProject = new FileInfo(projectCsprojPath); + var solution = new FileInfo(solutionFilePath); - var (generatedProject, renderedFiles) = - Renderer.Render(stat.Results(), testedProject, declaringType, solution, targetFramework); + var (generatedProject, renderedFiles) = + Renderer.Render(stat.Results(), testedProject, declaringType, solution, targetFramework); - return new GenerateResults( - generatedProject.FullName, - renderedFiles, - null, - (int)stat.TestsCount, - (int)stat.ErrorsCount); + return new GenerateResults( + generatedProject.FullName, + renderedFiles, + null, + (int)stat.TestsCount, + (int)stat.ErrorsCount); + } } private static bool MatchesType(TypeDescriptor typeDescriptor, Type typ) @@ -198,7 +206,8 @@ public static void Main(string[] args) { try { - return GenerateImpl(arguments); + var assemblyToPath = arguments.AssembliesFullNameToTheirPath.ToDictionary(it => it.Key, it => it.Value); + return GenerateImpl(arguments, assemblyToPath); } catch (Exception e) { @@ -206,6 +215,20 @@ public static void Main(string[] args) } finally { + var pathToCsProject = arguments.ProjectCsprojPath; + var csProjFile = new FileInfo(pathToCsProject); + if (csProjFile.Exists) + { + var csProjDir = csProjFile.Directory; + var vSharpDirs = csProjDir!.GetDirectories(); + foreach(var dir in vSharpDirs) + { + if (Regex.IsMatch(dir.Name, @"^VSharp\.tests\..+$")) + { + dir.Delete(recursive: true); + } + } + } scheduler.Queue(() => { blockingQueue.Add("End"); }); } }); @@ -219,8 +242,6 @@ public static void Main(string[] args) }); }); blockingQueue.Take(); - // todo check if queueing take as next action is enough - // Thread.Sleep(1000); ldef.Terminate(); } } diff --git a/utbot-rider/src/dotnet/UtBot/UtBot/Generated/UtBotRiderModel.Generated.cs b/utbot-rider/src/dotnet/UtBot/UtBot/Generated/UtBotRiderModel.Generated.cs new file mode 100644 index 0000000000..8c8db49fc1 --- /dev/null +++ b/utbot-rider/src/dotnet/UtBot/UtBot/Generated/UtBotRiderModel.Generated.cs @@ -0,0 +1,268 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a RdGen v1.10. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using JetBrains.Annotations; + +using JetBrains.Core; +using JetBrains.Diagnostics; +using JetBrains.Collections; +using JetBrains.Collections.Viewable; +using JetBrains.Lifetimes; +using JetBrains.Serialization; +using JetBrains.Rd; +using JetBrains.Rd.Base; +using JetBrains.Rd.Impl; +using JetBrains.Rd.Tasks; +using JetBrains.Rd.Util; +using JetBrains.Rd.Text; + + +// ReSharper disable RedundantEmptyObjectCreationArgumentList +// ReSharper disable InconsistentNaming +// ReSharper disable RedundantOverflowCheckingContext + + +namespace JetBrains.Rider.Model +{ + + + /// + ///

Generated from: RiderExtend.kt:8

+ ///
+ public class UtBotRiderModel : RdExtBase + { + //fields + //public fields + [NotNull] public ISignal StartPublish => _StartPublish; + [NotNull] public ISignal LogPublishOutput => _LogPublishOutput; + [NotNull] public ISignal LogPublishError => _LogPublishError; + [NotNull] public ISignal StopPublish => _StopPublish; + [NotNull] public ISignal StartVSharp => _StartVSharp; + [NotNull] public ISignal LogVSharp => _LogVSharp; + [NotNull] public ISignal StopVSharp => _StopVSharp; + + //private fields + [NotNull] private readonly RdSignal _StartPublish; + [NotNull] private readonly RdSignal _LogPublishOutput; + [NotNull] private readonly RdSignal _LogPublishError; + [NotNull] private readonly RdSignal _StopPublish; + [NotNull] private readonly RdSignal _StartVSharp; + [NotNull] private readonly RdSignal _LogVSharp; + [NotNull] private readonly RdSignal _StopVSharp; + + //primary constructor + private UtBotRiderModel( + [NotNull] RdSignal startPublish, + [NotNull] RdSignal logPublishOutput, + [NotNull] RdSignal logPublishError, + [NotNull] RdSignal stopPublish, + [NotNull] RdSignal startVSharp, + [NotNull] RdSignal logVSharp, + [NotNull] RdSignal stopVSharp + ) + { + if (startPublish == null) throw new ArgumentNullException("startPublish"); + if (logPublishOutput == null) throw new ArgumentNullException("logPublishOutput"); + if (logPublishError == null) throw new ArgumentNullException("logPublishError"); + if (stopPublish == null) throw new ArgumentNullException("stopPublish"); + if (startVSharp == null) throw new ArgumentNullException("startVSharp"); + if (logVSharp == null) throw new ArgumentNullException("logVSharp"); + if (stopVSharp == null) throw new ArgumentNullException("stopVSharp"); + + _StartPublish = startPublish; + _LogPublishOutput = logPublishOutput; + _LogPublishError = logPublishError; + _StopPublish = stopPublish; + _StartVSharp = startVSharp; + _LogVSharp = logVSharp; + _StopVSharp = stopVSharp; + _StartPublish.Async = true; + _LogPublishOutput.Async = true; + _LogPublishError.Async = true; + _StopPublish.Async = true; + _StartVSharp.Async = true; + _LogVSharp.Async = true; + _StopVSharp.Async = true; + BindableChildren.Add(new KeyValuePair("startPublish", _StartPublish)); + BindableChildren.Add(new KeyValuePair("logPublishOutput", _LogPublishOutput)); + BindableChildren.Add(new KeyValuePair("logPublishError", _LogPublishError)); + BindableChildren.Add(new KeyValuePair("stopPublish", _StopPublish)); + BindableChildren.Add(new KeyValuePair("startVSharp", _StartVSharp)); + BindableChildren.Add(new KeyValuePair("logVSharp", _LogVSharp)); + BindableChildren.Add(new KeyValuePair("stopVSharp", _StopVSharp)); + } + //secondary constructor + internal UtBotRiderModel ( + ) : this ( + new RdSignal(StartPublishArgs.Read, StartPublishArgs.Write), + new RdSignal(JetBrains.Rd.Impl.Serializers.ReadString, JetBrains.Rd.Impl.Serializers.WriteString), + new RdSignal(JetBrains.Rd.Impl.Serializers.ReadString, JetBrains.Rd.Impl.Serializers.WriteString), + new RdSignal(JetBrains.Rd.Impl.Serializers.ReadInt, JetBrains.Rd.Impl.Serializers.WriteInt), + new RdSignal(JetBrains.Rd.Impl.Serializers.ReadVoid, JetBrains.Rd.Impl.Serializers.WriteVoid), + new RdSignal(JetBrains.Rd.Impl.Serializers.ReadString, JetBrains.Rd.Impl.Serializers.WriteString), + new RdSignal(JetBrains.Rd.Impl.Serializers.ReadInt, JetBrains.Rd.Impl.Serializers.WriteInt) + ) {} + //deconstruct trait + //statics + + + + protected override long SerializationHash => 6014484928290881L; + + protected override Action Register => RegisterDeclaredTypesSerializers; + public static void RegisterDeclaredTypesSerializers(ISerializers serializers) + { + + serializers.RegisterToplevelOnce(typeof(IdeRoot), IdeRoot.RegisterDeclaredTypesSerializers); + } + + + //constants + + //custom body + //methods + //equals trait + //hash code trait + //pretty print + public override void Print(PrettyPrinter printer) + { + printer.Println("UtBotRiderModel ("); + using (printer.IndentCookie()) { + printer.Print("startPublish = "); _StartPublish.PrintEx(printer); printer.Println(); + printer.Print("logPublishOutput = "); _LogPublishOutput.PrintEx(printer); printer.Println(); + printer.Print("logPublishError = "); _LogPublishError.PrintEx(printer); printer.Println(); + printer.Print("stopPublish = "); _StopPublish.PrintEx(printer); printer.Println(); + printer.Print("startVSharp = "); _StartVSharp.PrintEx(printer); printer.Println(); + printer.Print("logVSharp = "); _LogVSharp.PrintEx(printer); printer.Println(); + printer.Print("stopVSharp = "); _StopVSharp.PrintEx(printer); printer.Println(); + } + printer.Print(")"); + } + //toString + public override string ToString() + { + var printer = new SingleLinePrettyPrinter(); + Print(printer); + return printer.ToString(); + } + } + public static class SolutionUtBotRiderModelEx + { + public static UtBotRiderModel GetUtBotRiderModel(this Solution solution) + { + return solution.GetOrCreateExtension("utBotRiderModel", () => new UtBotRiderModel()); + } + } + + + /// + ///

Generated from: RiderExtend.kt:9

+ ///
+ public sealed class StartPublishArgs : IPrintable, IEquatable + { + //fields + //public fields + [NotNull] public string FileName {get; private set;} + [NotNull] public string Arguments {get; private set;} + [NotNull] public string WorkingDirectory {get; private set;} + + //private fields + //primary constructor + public StartPublishArgs( + [NotNull] string fileName, + [NotNull] string arguments, + [NotNull] string workingDirectory + ) + { + if (fileName == null) throw new ArgumentNullException("fileName"); + if (arguments == null) throw new ArgumentNullException("arguments"); + if (workingDirectory == null) throw new ArgumentNullException("workingDirectory"); + + FileName = fileName; + Arguments = arguments; + WorkingDirectory = workingDirectory; + } + //secondary constructor + //deconstruct trait + public void Deconstruct([NotNull] out string fileName, [NotNull] out string arguments, [NotNull] out string workingDirectory) + { + fileName = FileName; + arguments = Arguments; + workingDirectory = WorkingDirectory; + } + //statics + + public static CtxReadDelegate Read = (ctx, reader) => + { + var fileName = reader.ReadString(); + var arguments = reader.ReadString(); + var workingDirectory = reader.ReadString(); + var _result = new StartPublishArgs(fileName, arguments, workingDirectory); + return _result; + }; + + public static CtxWriteDelegate Write = (ctx, writer, value) => + { + writer.Write(value.FileName); + writer.Write(value.Arguments); + writer.Write(value.WorkingDirectory); + }; + + //constants + + //custom body + //methods + //equals trait + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((StartPublishArgs) obj); + } + public bool Equals(StartPublishArgs other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return FileName == other.FileName && Arguments == other.Arguments && WorkingDirectory == other.WorkingDirectory; + } + //hash code trait + public override int GetHashCode() + { + unchecked { + var hash = 0; + hash = hash * 31 + FileName.GetHashCode(); + hash = hash * 31 + Arguments.GetHashCode(); + hash = hash * 31 + WorkingDirectory.GetHashCode(); + return hash; + } + } + //pretty print + public void Print(PrettyPrinter printer) + { + printer.Println("StartPublishArgs ("); + using (printer.IndentCookie()) { + printer.Print("fileName = "); FileName.PrintEx(printer); printer.Println(); + printer.Print("arguments = "); Arguments.PrintEx(printer); printer.Println(); + printer.Print("workingDirectory = "); WorkingDirectory.PrintEx(printer); printer.Println(); + } + printer.Print(")"); + } + //toString + public override string ToString() + { + var printer = new SingleLinePrettyPrinter(); + Print(printer); + return printer.ToString(); + } + } +} diff --git a/utbot-rider/src/dotnet/UtBot/UtBot/ProcessWithRdServer.cs b/utbot-rider/src/dotnet/UtBot/UtBot/ProcessWithRdServer.cs index d07baa7a75..0d7f3616ff 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot/ProcessWithRdServer.cs +++ b/utbot-rider/src/dotnet/UtBot/UtBot/ProcessWithRdServer.cs @@ -9,6 +9,7 @@ using JetBrains.Lifetimes; using JetBrains.Rd; using JetBrains.Rd.Impl; +using JetBrains.Rider.Model; using JetBrains.Threading; using JetBrains.Util; using JetBrains.Util.Logging; @@ -25,9 +26,9 @@ public class ProcessWithRdServer [CanBeNull] public VSharpModel VSharpModel { get; private set; } private readonly LifetimeDefinition _ldef; - [CanBeNull] private Process _process; + public readonly Process Proc = new(); - public ProcessWithRdServer(string name, string workingDir, int port, string exePath, IShellLocks shellLocks, Lifetime? parent = null, [CanBeNull] ILogger logger = null) + public ProcessWithRdServer(string name, string workingDir, int port, string exePath, IShellLocks shellLocks, UtBotRiderModel riderModel, Lifetime? parent = null, [CanBeNull] ILogger logger = null) { logger ??= Logger.GetLogger(); using var blockingCollection = new BlockingCollection(2); @@ -47,7 +48,7 @@ public ProcessWithRdServer(string name, string workingDir, int port, string exeP { WorkingDirectory = workingDir }; - + riderModel.StartVSharp.Fire(); Protocol = new Protocol(name, serializers, identities, scheduler, wire, Lifetime); scheduler.Queue(() => { @@ -59,22 +60,25 @@ public ProcessWithRdServer(string name, string workingDir, int port, string exeP blockingCollection.TryAdd(s); } }); - VSharpModel.Log.Advise(Lifetime, s => logger.Info($"V#: {s}")); + VSharpModel.Log.Advise(Lifetime, s => + { + logger.Info($"V#: {s}"); + riderModel.LogVSharp.Fire(s); + }); }); - _process = new Process(); - _process.StartInfo = startInfo; - Lifetime.OnTermination(() => _process.Kill(entireProcessTree: true)); - if (_process.Start()) - _process.Exited += (_, _) => _ldef.Terminate(); + Proc.StartInfo = startInfo; + Lifetime.OnTermination(() => Proc.Kill(entireProcessTree: true)); + if (Proc.Start()) + Proc.Exited += (_, _) => _ldef.Terminate(); else _ldef.Terminate(); }); - if (_process?.HasExited == true) return; + if (Proc?.HasExited == true) return; SpinWaitEx.SpinUntil(pingLdef.Lifetime, () => { - if (_process?.HasExited == true) + if (Proc?.HasExited == true) { VSharpModel = null; _ldef.Terminate(); diff --git a/utbot-rider/src/dotnet/UtBot/UtBot/UnitTestBuilder.cs b/utbot-rider/src/dotnet/UtBot/UtBot/UnitTestBuilder.cs index ad1e5e3e34..e0cc0a98e2 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot/UnitTestBuilder.cs +++ b/utbot-rider/src/dotnet/UtBot/UtBot/UnitTestBuilder.cs @@ -23,6 +23,7 @@ using JetBrains.ReSharper.Psi.Util; using JetBrains.Rider.Model; using JetBrains.Util; +using JetBrains.Util.Threading; using UtBot.Rd; using UtBot.Rd.Generated; using UtBot.Utils; @@ -39,28 +40,23 @@ internal sealed class UnitTestBuilder : GeneratorBuilderBase>()) { var methodName = inputElement.DeclaredElement.ShortName; - var hasNoOverLoads = typeElement.GetMembers().Count(m => m.ShortName == methodName) == 1; + var hasNoOverLoads = typeElement.GetAllClassMembers().Count(m => m.Member.ShortName == methodName) == 1; var parameterDescriptors = new List(); @@ -202,17 +198,10 @@ private void Generate(IBackgroundProgressIndicator progressIndicator, IProject p var config = project.ProjectProperties.ActiveConfigurations.Configurations.First(); var outputDir = project.GetOutputDirectory(config.TargetFrameworkId).Combine(PublishDirName); progressIndicator.Header.SetValue($"Publishing dependencies to {PublishDirName}..."); - try - { - _publisher.PublishSync(project, config, outputDir); - } - catch (Exception e) - { - var title = $"Cannot build project {project.Name}"; - var openExceptionMessageCommand = new UserNotificationCommand( - "Show error info", - () => MessageBox.ShowError(e.Message, title)); - _notifications.ShowError(title, command: openExceptionMessageCommand); + + if (!ProjectPublisher.PublishSync(_logger, progressIndicator, project, config, outputDir, _riderModel)) { + var title = $"Cannot publish project {project.Name}"; + _notifications.ShowError(title); return; } @@ -250,16 +239,27 @@ void ChangeMethodName() var workingDir = project.ProjectFileLocation.Directory.FullPath; var port = NetworkUtil.GetFreePort(); var runnerPath = vsharpRunner.FullPath; - var proc = new ProcessWithRdServer(name, workingDir, port, runnerPath, project.Locks, _lifetime, _logger); + var proc = new ProcessWithRdServer(name, workingDir, port, runnerPath, project.Locks, _riderModel, _lifetime, _logger); var projectCsprojPath = project.ProjectFileLocation.FullPath; + List allAssemblies; + using (_shellLocks.UsingReadLock()) + { + allAssemblies = solution.GetAllAssemblies() + .Where(it => it.Location.AssemblyPhysicalPath is not null) + .Select(it => new MapEntry(it.FullAssemblyName, it.Location.AssemblyPhysicalPath.FullPath)) + .DistinctBy(it => it.Key) + .ToList(); + } var args = new GenerateArguments(assemblyPath, projectCsprojPath, solutionFilePath, descriptors, - timeout, testProjectFramework.FrameworkMoniker.Name); + timeout, testProjectFramework.FrameworkMoniker.Name, allAssemblies); var vSharpTimeout = TimeSpan.FromSeconds(timeout); var rpcTimeout = new RpcTimeouts(vSharpTimeout + TimeSpan.FromSeconds(1), vSharpTimeout + TimeSpan.FromSeconds(30)); ChangeMethodName(); methodProgressTimer.Start(); var result = proc.VSharpModel?.Generate.Sync(args, rpcTimeout); methodProgressTimer.Stop(); + proc.Proc.WaitForExit(); + _riderModel.StopVSharp.Fire(proc.Proc.ExitCode); _logger.Info("Result acquired"); if (result is { GeneratedProjectPath: not null }) { diff --git a/utbot-rider/src/dotnet/UtBot/UtBot/UtBot.csproj b/utbot-rider/src/dotnet/UtBot/UtBot/UtBot.csproj index 78b8b76011..5dea4513c8 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot/UtBot.csproj +++ b/utbot-rider/src/dotnet/UtBot/UtBot/UtBot.csproj @@ -6,7 +6,7 @@ - + @@ -17,4 +17,8 @@ + + + + \ No newline at end of file diff --git a/utbot-rider/src/dotnet/UtBot/UtBot/Utils/DotNetVersionUtils.cs b/utbot-rider/src/dotnet/UtBot/UtBot/Utils/DotNetVersionUtils.cs index 280109dd98..48aa3380f9 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot/Utils/DotNetVersionUtils.cs +++ b/utbot-rider/src/dotnet/UtBot/UtBot/Utils/DotNetVersionUtils.cs @@ -10,22 +10,14 @@ namespace UtBot.Utils; internal readonly record struct TestProjectTargetFramework(FrameworkMoniker FrameworkMoniker, bool IsDefault); -[SolutionComponent] -internal class DotNetVersionUtils +internal static class DotNetVersionUtils { - public const int MinCompatibleSdkMajor = 6; + public const int MinCompatibleSdkMajor = 7; private const string NUnitProjectMinTfm = "net6.0"; - private readonly Lazy _canRunVSharp; + public static bool CanRunVSharp(ISolution solution) => GetCanRunVSharp(solution.SolutionDirectory.FullPath); - public DotNetVersionUtils(ISolution solution) - { - _canRunVSharp = new Lazy(() => GetCanRunVSharp(solution.SolutionDirectory.FullPath)); - } - - public bool CanRunVSharp => _canRunVSharp.Value; - - public TestProjectTargetFramework GetTestProjectFramework(IProject project) + public static TestProjectTargetFramework GetTestProjectFramework(IProject project) { var path = project.ProjectFileLocation.Directory.FullPath; @@ -115,7 +107,7 @@ private static bool GetCanRunVSharp(string workingDir) return false; } - private IEnumerable GetTfms(IProject project) => + private static IEnumerable GetTfms(IProject project) => project.TargetFrameworkIds .Select(i => new FrameworkMoniker(i.TryGetShortIdentifier())); diff --git a/utbot-rider/src/dotnet/UtBot/UtBot/Utils/ProjectPublisher.cs b/utbot-rider/src/dotnet/UtBot/UtBot/Utils/ProjectPublisher.cs index 1fc91aefde..8358bc2c02 100644 --- a/utbot-rider/src/dotnet/UtBot/UtBot/Utils/ProjectPublisher.cs +++ b/utbot-rider/src/dotnet/UtBot/UtBot/Utils/ProjectPublisher.cs @@ -2,32 +2,28 @@ using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; +using JetBrains.Application.Threading.Tasks; +using JetBrains.Application.UI.Controls; using JetBrains.Collections.Viewable; using JetBrains.Lifetimes; using JetBrains.ProjectModel; using JetBrains.ProjectModel.Properties; +using JetBrains.Rider.Model; using JetBrains.Threading; using JetBrains.Util; +using UtBot.Rd.Generated; namespace UtBot.Utils; -[SolutionComponent] -public class ProjectPublisher +public static class ProjectPublisher { - private readonly LifetimeDefinition _lifetimeDef; - - public ProjectPublisher(Lifetime lifetime) + public static bool PublishSync(ILogger logger, IBackgroundProgressIndicator indicator, IProject project, IProjectConfiguration config, VirtualFileSystemPath outputDir, UtBotRiderModel model) { - _lifetimeDef = lifetime.CreateNested(); - } - - public void PublishSync(IProject project, IProjectConfiguration config, VirtualFileSystemPath outputDir) - { - var publishLifetimeDef = _lifetimeDef.Lifetime.CreateNested(); + var publishLifetimeDef = indicator.Lifetime.CreateNested(); + indicator.Cancel.Advise(Lifetime.Eternal, canceled => {if (canceled) publishLifetimeDef.Terminate();}); try { - var name = $"Publish::{project.Name}"; Directory.CreateDirectory(outputDir.FullPath); var projectName = project.ProjectFileLocation.Name; var architecture = GetArchitecture(); @@ -45,35 +41,46 @@ public void PublishSync(IProject project, IProjectConfiguration config, VirtualF Arguments = $"{command} \"{projectName}\" --sc -c {config.Name} -a {architecture} -o {outputDir.FullPath} -f {tfm}", WorkingDirectory = project.ProjectFileLocation.Directory.FullPath, - RedirectStandardError = true, - RedirectStandardOutput = true + RedirectStandardOutput = true, + RedirectStandardError = true }; - var process = new Process(); + using var process = new Process(); process.StartInfo = processInfo; + process.OutputDataReceived += (_, args) => + { + model.LogPublishOutput.Fire(args.Data ?? "\n"); + }; + process.ErrorDataReceived += (_, args) => + { + model.LogPublishError.Fire(args.Data ?? "\n"); + }; process.Exited += (_, a) => { + publishLifetimeDef.Terminate(); + }; + model.StartPublish.Fire(new StartPublishArgs(processInfo.FileName, processInfo.Arguments, processInfo.WorkingDirectory)); + if (process.Start()) + { + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + SpinWaitEx.SpinUntil(publishLifetimeDef.Lifetime, () => process.HasExited); if (process.ExitCode != 0) { - throw new Exception( - $"Publish process exited with code {process.ExitCode}: {process.StandardOutput.ReadToEnd()}"); + logger.Warn($"Publish process exited with code {process.ExitCode}: {process.StandardOutput.ReadToEnd()}"); } - - publishLifetimeDef.Terminate(); - }; - - void Schedule(SingleThreadScheduler scheduler) + model.StopPublish.Fire(process.ExitCode); + } + else { - process.Start(); - process.WaitForExit(); + model.StopPublish.Fire(-1); } - - SingleThreadScheduler.RunOnSeparateThread(publishLifetimeDef.Lifetime, name, Schedule); - SpinWaitEx.SpinUntil(publishLifetimeDef.Lifetime, () => process.HasExited); + return process.HasExited && process.ExitCode == 0; } catch (Exception e) { - throw; + logger.Warn(e, comment: "Could not publish project for VSharp, exception occured"); + return false; } finally { @@ -81,7 +88,7 @@ void Schedule(SingleThreadScheduler scheduler) } } - private string GetArchitecture() + private static string GetArchitecture() { var arch = RuntimeInformation.OSArchitecture; return arch switch diff --git a/utbot-rider/src/main/kotlin/org/utbot/rider/UtBotConsoleViewComponent.kt b/utbot-rider/src/main/kotlin/org/utbot/rider/UtBotConsoleViewComponent.kt new file mode 100644 index 0000000000..25b3c7c61b --- /dev/null +++ b/utbot-rider/src/main/kotlin/org/utbot/rider/UtBotConsoleViewComponent.kt @@ -0,0 +1,118 @@ +package org.utbot.rider + +import com.intellij.execution.executors.DefaultRunExecutor +import com.intellij.execution.filters.TextConsoleBuilderFactory +import com.intellij.execution.ui.ConsoleView +import com.intellij.execution.ui.ConsoleViewContentType +import com.intellij.execution.ui.RunContentDescriptor +import com.intellij.execution.ui.RunContentManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.rd.createLifetime +import com.jetbrains.rd.platform.util.idea.ProtocolSubscribedProjectComponent +import com.jetbrains.rd.platform.util.lifetime +import com.jetbrains.rd.util.lifetime.Lifetime +import com.jetbrains.rd.util.reactive.ISignal +import com.jetbrains.rider.projectView.solution +import org.utbot.rider.generated.UtBotRiderModel +import org.utbot.rider.generated.utBotRiderModel +import kotlin.random.Random + +private fun ConsoleView.printYellowLine(any: Any) { + print("$any\n", ConsoleViewContentType.LOG_INFO_OUTPUT) +} + +private fun ConsoleView.printNormalLine(any: Any) { + print("$any\n", ConsoleViewContentType.NORMAL_OUTPUT) +} + +private fun ConsoleView.printErrorLine(any: Any) { + print("$any\n", ConsoleViewContentType.ERROR_OUTPUT) +} + +private fun ISignal.advisePrintExitCode(lifetime: Lifetime, consoleView: ConsoleView) { + advise(lifetime) { exitCode -> + val msg = "Process exited with code: $exitCode" + if (exitCode == 0) + consoleView.printNormalLine(msg) + else + consoleView.printErrorLine(msg) + } +} + +private fun ISignal.advisePrintNormal(lifetime: Lifetime, consoleView: ConsoleView) { + advise(lifetime) { output -> + consoleView.printNormalLine(output) + } +} + +private fun ISignal.advisePrintError(lifetime: Lifetime, consoleView: ConsoleView) { + advise(lifetime) { output -> + consoleView.printErrorLine(output) + } +} + +class UtBotConsoleViewComponent(project: Project) : ProtocolSubscribedProjectComponent(project) { + private var currentExecutionId: Long = -1 + private val model: UtBotRiderModel + + private fun update( + firstLine: String, + displayName: String, + previous: RunContentDescriptor? + ): Triple { + val textConsoleBuilderFactory = TextConsoleBuilderFactory.getInstance() + val consoleView = textConsoleBuilderFactory.createBuilder(project).console + val runContentDescriptor = + RunContentDescriptor(consoleView, null, consoleView.component, displayName).apply { + executionId = currentExecutionId + } + val runContentManager = RunContentManager.getInstance(project) + + runContentManager.showRunContent( + DefaultRunExecutor.getRunExecutorInstance(), + runContentDescriptor, + previous + ) + consoleView.printYellowLine(firstLine) + + return Triple(runContentDescriptor, consoleView, consoleView.createLifetime()) + } + + private fun initPublish() { + var previousPublish: RunContentDescriptor? = null + model.startPublish.advise(project.lifetime) { publishArgs -> + currentExecutionId = Random.nextLong() + val (fileName, arguments, workingDirectory) = publishArgs + val firstLine = "$workingDirectory .> $fileName $arguments" + val (currentPublish, consoleView, consoleLifetime) = update( + firstLine, + "Project publish for UtBot", + previousPublish + ) + previousPublish = currentPublish + model.logPublishOutput.advisePrintNormal(consoleLifetime, consoleView) + model.logPublishError.advisePrintError(consoleLifetime, consoleView) + model.stopPublish.advisePrintExitCode(consoleLifetime, consoleView) + } + } + + init { + model = project.solution.utBotRiderModel + initPublish() + initVSharp() + } + + private fun initVSharp() { + var previousVSharp: RunContentDescriptor? = null + model.startVSharp.advise(project.lifetime) { + val (currentVSharp, consoleView, consoleLifetime) = update( + "Started VSharp Engine", + "Running VSharp Engine", + previousVSharp + ) + previousVSharp = currentVSharp + model.logVSharp.advisePrintNormal(consoleLifetime, consoleView) + model.stopVSharp.advisePrintExitCode(consoleLifetime, consoleView) + } + } +} \ No newline at end of file diff --git a/utbot-rider/src/main/kotlin/org/utbot/rider/generated/UtBotRiderModel.Generated.kt b/utbot-rider/src/main/kotlin/org/utbot/rider/generated/UtBotRiderModel.Generated.kt new file mode 100644 index 0000000000..105a25a998 --- /dev/null +++ b/utbot-rider/src/main/kotlin/org/utbot/rider/generated/UtBotRiderModel.Generated.kt @@ -0,0 +1,190 @@ +@file:Suppress("EXPERIMENTAL_API_USAGE","EXPERIMENTAL_UNSIGNED_LITERALS","PackageDirectoryMismatch","UnusedImport","unused","LocalVariableName","CanBeVal","PropertyName","EnumEntryName","ClassName","ObjectPropertyName","UnnecessaryVariable","SpellCheckingInspection") +package org.utbot.rider.generated + +import com.jetbrains.rd.framework.* +import com.jetbrains.rd.framework.base.* +import com.jetbrains.rd.framework.impl.* +import com.jetbrains.rd.ide.model.Solution + +import com.jetbrains.rd.util.lifetime.* +import com.jetbrains.rd.util.reactive.* +import com.jetbrains.rd.util.string.* +import com.jetbrains.rd.util.* +import kotlin.reflect.KClass +import kotlin.jvm.JvmStatic + + + +/** + * #### Generated from [RiderExtend.kt:8] + */ +class UtBotRiderModel private constructor( + private val _startPublish: RdSignal, + private val _logPublishOutput: RdSignal, + private val _logPublishError: RdSignal, + private val _stopPublish: RdSignal, + private val _startVSharp: RdSignal, + private val _logVSharp: RdSignal, + private val _stopVSharp: RdSignal +) : RdExtBase() { + //companion + + companion object : ISerializersOwner { + + override fun registerSerializersCore(serializers: ISerializers) { + serializers.register(StartPublishArgs) + } + + + + + + const val serializationHash = 6014484928290881L + + } + override val serializersOwner: ISerializersOwner get() = UtBotRiderModel + override val serializationHash: Long get() = UtBotRiderModel.serializationHash + + //fields + val startPublish: IAsyncSignal get() = _startPublish + val logPublishOutput: IAsyncSignal get() = _logPublishOutput + val logPublishError: IAsyncSignal get() = _logPublishError + val stopPublish: IAsyncSignal get() = _stopPublish + val startVSharp: IAsyncSignal get() = _startVSharp + val logVSharp: IAsyncSignal get() = _logVSharp + val stopVSharp: IAsyncSignal get() = _stopVSharp + //methods + //initializer + init { + _startPublish.async = true + _logPublishOutput.async = true + _logPublishError.async = true + _stopPublish.async = true + _startVSharp.async = true + _logVSharp.async = true + _stopVSharp.async = true + } + + init { + bindableChildren.add("startPublish" to _startPublish) + bindableChildren.add("logPublishOutput" to _logPublishOutput) + bindableChildren.add("logPublishError" to _logPublishError) + bindableChildren.add("stopPublish" to _stopPublish) + bindableChildren.add("startVSharp" to _startVSharp) + bindableChildren.add("logVSharp" to _logVSharp) + bindableChildren.add("stopVSharp" to _stopVSharp) + } + + //secondary constructor + internal constructor( + ) : this( + RdSignal(StartPublishArgs), + RdSignal(FrameworkMarshallers.String), + RdSignal(FrameworkMarshallers.String), + RdSignal(FrameworkMarshallers.Int), + RdSignal(FrameworkMarshallers.Void), + RdSignal(FrameworkMarshallers.String), + RdSignal(FrameworkMarshallers.Int) + ) + + //equals trait + //hash code trait + //pretty print + override fun print(printer: PrettyPrinter) { + printer.println("UtBotRiderModel (") + printer.indent { + print("startPublish = "); _startPublish.print(printer); println() + print("logPublishOutput = "); _logPublishOutput.print(printer); println() + print("logPublishError = "); _logPublishError.print(printer); println() + print("stopPublish = "); _stopPublish.print(printer); println() + print("startVSharp = "); _startVSharp.print(printer); println() + print("logVSharp = "); _logVSharp.print(printer); println() + print("stopVSharp = "); _stopVSharp.print(printer); println() + } + printer.print(")") + } + //deepClone + override fun deepClone(): UtBotRiderModel { + return UtBotRiderModel( + _startPublish.deepClonePolymorphic(), + _logPublishOutput.deepClonePolymorphic(), + _logPublishError.deepClonePolymorphic(), + _stopPublish.deepClonePolymorphic(), + _startVSharp.deepClonePolymorphic(), + _logVSharp.deepClonePolymorphic(), + _stopVSharp.deepClonePolymorphic() + ) + } + //contexts +} +val Solution.utBotRiderModel get() = getOrCreateExtension("utBotRiderModel", ::UtBotRiderModel) + + + +/** + * #### Generated from [RiderExtend.kt:9] + */ +data class StartPublishArgs ( + val fileName: String, + val arguments: String, + val workingDirectory: String +) : IPrintable { + //companion + + companion object : IMarshaller { + override val _type: KClass = StartPublishArgs::class + + @Suppress("UNCHECKED_CAST") + override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): StartPublishArgs { + val fileName = buffer.readString() + val arguments = buffer.readString() + val workingDirectory = buffer.readString() + return StartPublishArgs(fileName, arguments, workingDirectory) + } + + override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: StartPublishArgs) { + buffer.writeString(value.fileName) + buffer.writeString(value.arguments) + buffer.writeString(value.workingDirectory) + } + + + } + //fields + //methods + //initializer + //secondary constructor + //equals trait + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || other::class != this::class) return false + + other as StartPublishArgs + + if (fileName != other.fileName) return false + if (arguments != other.arguments) return false + if (workingDirectory != other.workingDirectory) return false + + return true + } + //hash code trait + override fun hashCode(): Int { + var __r = 0 + __r = __r*31 + fileName.hashCode() + __r = __r*31 + arguments.hashCode() + __r = __r*31 + workingDirectory.hashCode() + return __r + } + //pretty print + override fun print(printer: PrettyPrinter) { + printer.println("StartPublishArgs (") + printer.indent { + print("fileName = "); fileName.print(printer); println() + print("arguments = "); arguments.print(printer); println() + print("workingDirectory = "); workingDirectory.print(printer); println() + } + printer.print(")") + } + //deepClone + //contexts +} diff --git a/utbot-rider/src/main/resources/META-INF/plugin.xml b/utbot-rider/src/main/resources/META-INF/plugin.xml index 0a9c9dd0e8..1b60aceb7d 100644 --- a/utbot-rider/src/main/resources/META-INF/plugin.xml +++ b/utbot-rider/src/main/resources/META-INF/plugin.xml @@ -22,4 +22,22 @@ ]]> + + + org.utbot.rider.UtBotConsoleViewComponent + + + + + +
  • Test generation timeout option to control test generation duration
  • +
  • Balloon notifications informing about the test generation process state
  • +
  • Console output for publish and test generation processes
  • +
  • .NET 7 projects support
  • +
  • Bugfixes
  • + + ]]> +