Skip to content

Required libraries can be installed silently #492 #494

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,12 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
setResizable(false)

// Configure notification urls callbacks
TestReportUrlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoSuffix]?.plusAssign {
if (createMockFrameworkNotificationDialog() == Messages.YES) {
configureMockFramework()
}
TestsReportNotifier.urlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoSuffix]?.plusAssign {
configureMockFramework()
}

TestReportUrlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoInlineSuffix]?.plusAssign {
if (createStaticsMockingNotificationDialog() == Messages.YES) {
configureStaticMocking()
}
TestsReportNotifier.urlOpeningListener.callbacks[TestReportUrlOpeningListener.mockitoInlineSuffix]?.plusAssign {
configureStaticMocking()
}

TestReportUrlOpeningListener.callbacks[TestReportUrlOpeningListener.eventLogSuffix]?.plusAssign {
Expand Down Expand Up @@ -619,29 +615,21 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
//region configure frameworks

private fun configureTestFrameworkIfRequired() {
val frameworkNotInstalled = !testFrameworks.item.isInstalled

if (frameworkNotInstalled && createTestFrameworkNotificationDialog() == Messages.YES) {
if (!testFrameworks.item.isInstalled) {
configureTestFramework()
}

model.conflictTriggers[Conflict.TestFrameworkConflict] = TestFramework.allItems.count { it.isInstalled } > 1
}

private fun configureMockFrameworkIfRequired() {
val frameworkNotInstalled =
mockStrategies.item != MockStrategyApi.NO_MOCKS && !MOCKITO.isInstalled

if (frameworkNotInstalled && createMockFrameworkNotificationDialog() == Messages.YES) {
if (mockStrategies.item != MockStrategyApi.NO_MOCKS && !MOCKITO.isInstalled) {
configureMockFramework()
}
}

private fun configureStaticMockingIfRequired() {
val frameworkNotConfigured =
staticsMocking.item != NoStaticMocking && !staticsMocking.item.isConfigured

if (frameworkNotConfigured && createStaticsMockingNotificationDialog() == Messages.YES) {
if (staticsMocking.item != NoStaticMocking && !staticsMocking.item.isConfigured) {
configureStaticMocking()
}
}
Expand All @@ -664,15 +652,6 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
.onError { selectedTestFramework.isInstalled = false }
}

private fun createTestFrameworkNotificationDialog() = Messages.showYesNoDialog(
"""Selected test framework ${testFrameworks.item.displayName} is not installed into current module.
|Would you like to install it now?""".trimMargin(),
title,
"Yes",
"No",
Messages.getQuestionIcon(),
)

private fun configureMockFramework() {
val selectedMockFramework = MOCKITO

Expand Down Expand Up @@ -749,24 +728,6 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
}
}

private fun createMockFrameworkNotificationDialog() = Messages.showYesNoDialog(
"""Mock framework ${MOCKITO.displayName} is not installed into current module.
|Would you like to install it now?""".trimMargin(),
title,
"Yes",
"No",
Messages.getQuestionIcon(),
)

private fun createStaticsMockingNotificationDialog() = Messages.showYesNoDialog(
"""A framework ${MOCKITO.displayName} is not configured to mock static methods.
|Would you like to configure it now?""".trimMargin(),
title,
"Yes",
"No",
Messages.getQuestionIcon(),
)

//endregion

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.utbot.intellij.plugin.util

import com.intellij.codeInsight.daemon.impl.quickfix.LocateLibraryDialog
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix
import com.intellij.jarRepository.JarRepositoryManager
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ExternalLibraryDescriptor
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.impl.IdeaProjectModelModifier
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar
import com.intellij.openapi.roots.libraries.LibraryUtil
import com.intellij.util.PathUtil
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.resolvedPromise
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryDescription
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryProperties
import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor

class UtProjectModelModifier(val project: Project) : IdeaProjectModelModifier(project) {
override fun addExternalLibraryDependency(
modules: Collection<Module>,
descriptor: ExternalLibraryDescriptor,
scope: DependencyScope
): Promise<Void>? {
val defaultRoots = descriptor.libraryClassesRoots
val firstModule = ContainerUtil.getFirstItem(modules) ?: return null
val classesRoots = if (defaultRoots.isNotEmpty()) {
LocateLibraryDialog(
firstModule,
defaultRoots,
descriptor.presentableName
).showAndGetResult()
} else {
val roots = JarRepositoryManager.loadDependenciesModal(
project,
RepositoryLibraryProperties(JpsMavenRepositoryLibraryDescriptor(descriptor.mavenCoordinates())),
/* loadSources = */ false,
/* loadJavadoc = */ false,
/* copyTo = */ null,
/* repositories = */ null
)
if (roots.isEmpty()) {
return null
}
roots.filter { orderRoot -> orderRoot.type === OrderRootType.CLASSES }
.map { PathUtil.getLocalPath(it.file) }.toList()
}
if (classesRoots.isNotEmpty()) {
val urls = OrderEntryFix.refreshAndConvertToUrls(classesRoots)
if (modules.size == 1) {
ModuleRootModificationUtil.addModuleLibrary(
firstModule,
if (classesRoots.size > 1) descriptor.presentableName else null,
urls,
emptyList(),
scope
)
} else {
WriteAction.run<RuntimeException> {
LibraryUtil.createLibrary(
LibraryTablesRegistrar.getInstance().getLibraryTable(project),
descriptor.presentableName
).let {
val model = it.modifiableModel
urls.forEach { url -> model.addRoot(url, OrderRootType.CLASSES) }
model.commit()
modules.forEach { module ->
ModuleRootModificationUtil.addDependency(module, it, scope, false)
}
}
}
}
}
return resolvedPromise()
}

private fun ExternalLibraryDescriptor.mavenCoordinates(): String {
return "$libraryGroupId:$libraryArtifactId:${preferredVersion ?: RepositoryLibraryDescription.ReleaseVersionId}"
}
}
1 change: 1 addition & 0 deletions utbot-intellij/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<projectService serviceImplementation="org.utbot.intellij.plugin.settings.Settings" preload="true"/>
<registryKey defaultValue="false" description="Enable editing Kotlin test files" key="kotlin.ultra.light.classes.empty.text.range"/>
<postStartupActivity implementation="org.utbot.intellij.plugin.ui.GotItTooltipActivity"/>
<projectModelModifier implementation="org.utbot.intellij.plugin.util.UtProjectModelModifier"/>
</extensions>

<!-- Minimum and maximum build of IDE compatible with the plugin -->
Expand Down