Skip to content

Commit

Permalink
RUN: Implicitly pass required features to a run configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
mchernyavsky committed Oct 31, 2020
1 parent 05fd745 commit e6242b7
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import org.rust.cargo.runconfig.buildtool.CargoBuildManager.isBuildConfiguration
import org.rust.cargo.runconfig.buildtool.CargoBuildManager.isBuildToolWindowEnabled
import org.rust.cargo.runconfig.buildtool.cargoPatches
import org.rust.cargo.runconfig.command.CargoCommandConfiguration
import org.rust.cargo.toolchain.tools.Cargo.Companion.cargoCommonPatch
import org.rust.cargo.toolchain.tools.Cargo.Companion.getCargoCommonPatch
import org.rust.cargo.toolchain.tools.RsTool.Companion.createGeneralCommandLine
import org.rust.cargo.util.CargoArgsParser.Companion.parseArgs
import org.rust.openapiext.computeWithCancelableProgress
Expand Down Expand Up @@ -52,7 +52,7 @@ abstract class RsExecutableRunner(
processInvalidToolchain(project, toolchainError)
return
}
environment.cargoPatches += cargoCommonPatch
environment.cargoPatches += getCargoCommonPatch(project)
environment.putUserData(BINARIES, CompletableFuture())
super.execute(environment)
}
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/org/rust/cargo/runconfig/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fun CargoCommandLine.mergeWithDefault(default: CargoCommandConfiguration): Cargo
backtraceMode = default.backtrace,
channel = default.channel,
environmentVariables = default.env,
requiredFeatures = default.requiredFeatures,
allFeatures = default.allFeatures,
emulateTerminal = default.emulateTerminal
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.jdom.Element
import org.rust.cargo.project.model.CargoProject
import org.rust.cargo.project.model.cargoProjects
import org.rust.cargo.project.settings.toolchain
import org.rust.cargo.project.workspace.CargoWorkspace
import org.rust.cargo.runconfig.*
import org.rust.cargo.runconfig.buildtool.CargoBuildTaskProvider
import org.rust.cargo.runconfig.ui.CargoCommandConfigurationEditor
Expand Down Expand Up @@ -46,6 +47,7 @@ class CargoCommandConfiguration(

var channel: RustChannel = RustChannel.DEFAULT
var command: String = "run"
var requiredFeatures: Boolean = true
var allFeatures: Boolean = false
var emulateTerminal: Boolean = false
var backtrace: BacktraceMode = BacktraceMode.SHORT
Expand All @@ -65,6 +67,7 @@ class CargoCommandConfiguration(
super.writeExternal(element)
element.writeEnum("channel", channel)
element.writeString("command", command)
element.writeBool("requitedFeatures", requiredFeatures)
element.writeBool("allFeatures", allFeatures)
element.writeBool("emulateTerminal", emulateTerminal)
element.writeEnum("backtrace", backtrace)
Expand All @@ -80,6 +83,7 @@ class CargoCommandConfiguration(
super.readExternal(element)
element.readEnum<RustChannel>("channel")?.let { channel = it }
element.readString("command")?.let { command = it }
element.readBool("requiredFeatures")?.let { requiredFeatures = it }
element.readBool("allFeatures")?.let { allFeatures = it }
element.readBool("emulateTerminal")?.let { emulateTerminal = it }
element.readEnum<BacktraceMode>("backtrace")?.let { backtrace = it }
Expand All @@ -90,6 +94,7 @@ class CargoCommandConfiguration(
fun setFromCmd(cmd: CargoCommandLine) {
channel = cmd.channel
command = ParametersListUtil.join(cmd.command, *cmd.additionalArguments.toTypedArray())
requiredFeatures = cmd.requiredFeatures
allFeatures = cmd.allFeatures
emulateTerminal = cmd.emulateTerminal
backtrace = cmd.backtraceMode
Expand Down Expand Up @@ -150,6 +155,7 @@ class CargoCommandConfiguration(
backtrace,
channel,
env,
requiredFeatures,
allFeatures,
emulateTerminal
)
Expand Down Expand Up @@ -193,6 +199,52 @@ class CargoCommandConfiguration(
fun findCargoProject(project: Project, cmd: String, workingDirectory: Path?): CargoProject? = findCargoProject(
project, ParametersListUtil.parse(cmd), workingDirectory
)

fun findCargoPackage(
cargoProject: CargoProject,
additionalArgs: List<String>,
workingDirectory: Path?
): CargoWorkspace.Package? {
val packages = cargoProject.workspace?.packages.orEmpty()
packages.singleOrNull()?.let { return it }

val packageName = run {
val idx = additionalArgs.indexOf("--package")
if (idx == -1) return@run null
additionalArgs.getOrNull(idx + 1)
}

if (packageName != null) {
return packages.find { it.name == packageName }
}

return packages.find { it.rootDirectory == workingDirectory }
}

fun findCargoTargets(
cargoPackage: CargoWorkspace.Package,
additionalArgs: List<String>
): List<CargoWorkspace.Target> {

fun hasTarget(option: String, name: String): Boolean {
if ("$option=$name" in additionalArgs) return true
return additionalArgs.windowed(2).any { pair ->
pair.first() == option && pair.last() == name
}
}

return cargoPackage.targets.filter { target ->
when (target.kind) {
CargoWorkspace.TargetKind.Bin -> hasTarget("--bin", target.name)
CargoWorkspace.TargetKind.Test -> hasTarget("--test", target.name)
CargoWorkspace.TargetKind.ExampleBin,
is CargoWorkspace.TargetKind.ExampleLib -> hasTarget("--example", target.name)
CargoWorkspace.TargetKind.Bench -> hasTarget("--bench", target.name)
is CargoWorkspace.TargetKind.Lib -> "--lib" in additionalArgs
else -> false
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import org.rust.cargo.runconfig.buildtool.CargoBuildManager.isBuildToolWindowEna
import org.rust.cargo.runconfig.command.CargoCommandConfiguration
import org.rust.cargo.toolchain.CargoCommandLine
import org.rust.cargo.toolchain.impl.CargoMetadata
import org.rust.cargo.toolchain.tools.Cargo.Companion.cargoCommonPatch
import org.rust.cargo.toolchain.tools.Cargo.Companion.getCargoCommonPatch
import org.rust.cargo.toolchain.tools.RsTool.Companion.createGeneralCommandLine
import org.rust.cargo.util.CargoArgsParser.Companion.parseArgs
import org.rust.openapiext.saveAllDocuments
Expand All @@ -60,7 +60,9 @@ abstract class RsAsyncRunner(
override fun execute(environment: ExecutionEnvironment, state: RunProfileState): Promise<RunContentDescriptor?> {
saveAllDocuments()

val commandLine = (state as CargoRunStateBase).prepareCommandLine(cargoCommonPatch)
state as CargoRunStateBase

val commandLine = state.prepareCommandLine(getCargoCommonPatch(environment.project))
val (commandArguments, executableArguments) = parseArgs(commandLine.command, commandLine.additionalArguments)

val isTestRun = commandLine.command == "test"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ class CargoCommandConfigurationEditor(project: Project)
}

private val environmentVariables = EnvironmentVariablesComponent()
private val requiredFeatures = CheckBox("Implicitly add required features if possible", true)
private val allFeatures = CheckBox("Use all features in tests", false)
private val emulateTerminal = CheckBox("Emulate terminal in output console", false)

override fun resetEditorFrom(configuration: CargoCommandConfiguration) {
channel.selectedIndex = configuration.channel.index
command.text = configuration.command
requiredFeatures.isSelected = configuration.requiredFeatures
allFeatures.isSelected = configuration.allFeatures
emulateTerminal.isSelected = configuration.emulateTerminal
backtraceMode.selectedIndex = configuration.backtrace.index
Expand All @@ -99,6 +101,7 @@ class CargoCommandConfigurationEditor(project: Project)

configuration.channel = configChannel
configuration.command = command.text
configuration.requiredFeatures = requiredFeatures.isSelected
configuration.allFeatures = allFeatures.isSelected
configuration.emulateTerminal = emulateTerminal.isSelected && !SystemInfo.isWindows
configuration.backtrace = BacktraceMode.fromIndex(backtraceMode.selectedIndex)
Expand All @@ -120,6 +123,7 @@ class CargoCommandConfigurationEditor(project: Project)
channel()
}

row { requiredFeatures() }
row { allFeatures() }

if (!SystemInfo.isWindows) {
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/org/rust/cargo/toolchain/CommandLine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ data class CargoCommandLine(
val backtraceMode: BacktraceMode = BacktraceMode.DEFAULT,
val channel: RustChannel = RustChannel.DEFAULT,
val environmentVariables: EnvironmentVariablesData = EnvironmentVariablesData.DEFAULT,
val requiredFeatures: Boolean = true,
val allFeatures: Boolean = false,
val emulateTerminal: Boolean = false
) : RsCommandLineBase() {
Expand Down
47 changes: 37 additions & 10 deletions src/main/kotlin/org/rust/cargo/toolchain/tools/Cargo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ import org.rust.cargo.project.workspace.CargoWorkspace
import org.rust.cargo.project.workspace.CargoWorkspaceData
import org.rust.cargo.project.workspace.PackageId
import org.rust.cargo.runconfig.buildtool.CargoPatch
import org.rust.cargo.runconfig.command.CargoCommandConfiguration.Companion.findCargoPackage
import org.rust.cargo.runconfig.command.CargoCommandConfiguration.Companion.findCargoProject
import org.rust.cargo.runconfig.command.CargoCommandConfiguration.Companion.findCargoTargets
import org.rust.cargo.runconfig.command.workingDirectory
import org.rust.cargo.toolchain.CargoCommandLine
import org.rust.cargo.toolchain.ExternalLinter
Expand Down Expand Up @@ -341,7 +343,7 @@ open class Cargo(toolchain: RsToolchain, useWrapper: Boolean = false)
toGeneralCommandLine(project, commandLine, colors = false)

private fun toGeneralCommandLine(project: Project, commandLine: CargoCommandLine, colors: Boolean): GeneralCommandLine =
with(patchArgs(commandLine, colors)) {
with(commandLine.patchArgs(project, colors)) {
val parameters = buildList<String> {
if (channel != RustChannel.DEFAULT) {
add("+$channel")
Expand Down Expand Up @@ -411,6 +413,10 @@ open class Cargo(toolchain: RsToolchain, useWrapper: Boolean = false)
const val NAME: String = "cargo"
const val WRAPPER_NAME: String = "xargo"

private val FEATURES_ACCEPTING_COMMANDS: List<String> = listOf(
"bench", "build", "check", "doc", "fix", "run", "rustc", "rustdoc", "test", "metadata", "tree", "install", "package", "publish"
)

private val COLOR_ACCEPTING_COMMANDS: List<String> = listOf(
"bench", "build", "check", "clean", "clippy", "doc", "install", "publish", "run", "rustc", "test", "update"
)
Expand All @@ -424,23 +430,44 @@ open class Cargo(toolchain: RsToolchain, useWrapper: Boolean = false)

data class GeneratedFilesHolder(val manifest: VirtualFile, val sourceFiles: List<VirtualFile>)

val cargoCommonPatch: CargoPatch = { patchArgs(it, true) }
fun getCargoCommonPatch(project: Project): CargoPatch = { it.patchArgs(project, true) }

fun patchArgs(commandLine: CargoCommandLine, colors: Boolean): CargoCommandLine {
val (pre, post) = commandLine.splitOnDoubleDash()
fun CargoCommandLine.patchArgs(project: Project, colors: Boolean): CargoCommandLine {
val (pre, post) = splitOnDoubleDash()
.let { (pre, post) -> pre.toMutableList() to post.toMutableList() }

if (commandLine.command == "test" && commandLine.allFeatures && !pre.contains("--all-features")) {
if (command == "test" && allFeatures && !pre.contains("--all-features")) {
pre.add("--all-features")
}

if (requiredFeatures && command in FEATURES_ACCEPTING_COMMANDS) {
run {
val cargoProject = findCargoProject(project, additionalArguments, workingDirectory) ?: return@run
val cargoPackage = findCargoPackage(cargoProject, additionalArguments, workingDirectory) ?: return@run
if (workingDirectory != cargoPackage.rootDirectory) {
val manifestIdx = pre.indexOf("--manifest-path")
if (manifestIdx != -1) return@run
val packageIdx = pre.indexOf("--package")
if (packageIdx == -1) return@run
pre.removeAt(packageIdx) // remove `--package`
pre.removeAt(packageIdx) // remove package name
pre.add("--manifest-path")
val manifest = cargoPackage.rootDirectory.resolve(CargoConstants.MANIFEST_FILE)
pre.add(manifest.toAbsolutePath().toString())
}
val cargoTargets = findCargoTargets(cargoPackage, additionalArguments)
val features = cargoTargets.flatMap { it.requiredFeatures }.distinct().joinToString(",")
if (features.isNotEmpty()) pre.add("--features=$features")
}
}

// Force colors
val forceColors = colors &&
commandLine.command in COLOR_ACCEPTING_COMMANDS &&
commandLine.additionalArguments.none { it.startsWith("--color") }
command in COLOR_ACCEPTING_COMMANDS &&
additionalArguments.none { it.startsWith("--color") }
if (forceColors) pre.add(0, "--color=always")

return commandLine.copy(additionalArguments = if (post.isEmpty()) pre else pre + "--" + post)
return copy(additionalArguments = if (post.isEmpty()) pre else pre + "--" + post)
}

fun checkNeedInstallGrcov(project: Project): Boolean {
Expand Down Expand Up @@ -535,14 +562,14 @@ sealed class CargoCheckArgs {
override val cargoProjectDirectory: Path,
val target: CargoWorkspace.Target,
override val extraArguments: String
): CargoCheckArgs()
) : CargoCheckArgs()

data class FullWorkspace(
override val linter: ExternalLinter,
override val cargoProjectDirectory: Path,
val allTargets: Boolean,
override val extraArguments: String
): CargoCheckArgs()
) : CargoCheckArgs()

companion object {
fun forTarget(project: Project, target: CargoWorkspace.Target): CargoCheckArgs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ class BenchRunConfigurationProducerTest : RunConfigurationProducerTestBase() {

modifyTemplateConfiguration {
channel = RustChannel.NIGHTLY
requiredFeatures = false
allFeatures = true
emulateTerminal = true
backtrace = BacktraceMode.FULL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ExecutableRunConfigurationProducerTest : RunConfigurationProducerTestBase(

modifyTemplateConfiguration {
channel = RustChannel.NIGHTLY
requiredFeatures = false
allFeatures = true
emulateTerminal = true
backtrace = BacktraceMode.FULL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class TestRunConfigurationProducerTest : RunConfigurationProducerTestBase() {

modifyTemplateConfiguration {
channel = RustChannel.NIGHTLY
requiredFeatures = false
allFeatures = true
emulateTerminal = true
backtrace = BacktraceMode.FULL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<configuration name="Bench bench_foo" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="NIGHTLY" />
<option name="command" value="bench --package test-package --lib bench_foo -- --exact" />
<option name="requiredFeatures" value="false" />
<option name="allFeatures" value="true" />
<option name="emulateTerminal" value="true" />
<option name="backtrace" value="FULL" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<configuration name="Run hello" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="NIGHTLY" />
<option name="command" value="run --package test-package --bin hello" />
<option name="requiredFeatures" value="false" />
<option name="allFeatures" value="true" />
<option name="emulateTerminal" value="true" />
<option name="backtrace" value="FULL" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<configuration name="Test test_foo" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="NIGHTLY" />
<option name="command" value="test --package test-package --lib test_foo -- --exact" />
<option name="requiredFeatures" value="false" />
<option name="allFeatures" value="true" />
<option name="emulateTerminal" value="true" />
<option name="backtrace" value="FULL" />
Expand Down

0 comments on commit e6242b7

Please sign in to comment.