From c8e502a4465dd1e8dbd00d249368b64279219f57 Mon Sep 17 00:00:00 2001 From: ortem Date: Thu, 29 Aug 2019 13:14:27 +0300 Subject: [PATCH 1/3] INT: Handle trailing comma in ChopListIntention --- .../rust/ide/intentions/ChopListIntention.kt | 6 ++-- .../org/rust/ide/intentions/ListIntention.kt | 16 +++++---- .../ChopArgumentListIntentionTest.kt | 33 ++++++++++++++++++- .../intentions/ChopFieldListIntentionTest.kt | 22 ++++++++++++- .../ChopParameterListIntentionTest.kt | 21 +++++++++++- .../ChopVariantListIntentionTest.kt | 22 ++++++++++++- 6 files changed, 106 insertions(+), 14 deletions(-) diff --git a/src/main/kotlin/org/rust/ide/intentions/ChopListIntention.kt b/src/main/kotlin/org/rust/ide/intentions/ChopListIntention.kt index c7bb9fa4125..ee98b801f2b 100644 --- a/src/main/kotlin/org/rust/ide/intentions/ChopListIntention.kt +++ b/src/main/kotlin/org/rust/ide/intentions/ChopListIntention.kt @@ -31,9 +31,9 @@ abstract class ChopListIntentionBase( val startOffset = ctx.startOffset val elements = ctx.elements - val last = elements.last() - if (!hasLineBreakAfter(last)) { - last.textRange?.endOffset?.also { document.insertString(it, "\n") } + val lastElementOrTrailingComma = elements.last().let { commaAfter(it) ?: it } + if (!hasLineBreakAfter(lastElementOrTrailingComma)) { + lastElementOrTrailingComma.textRange?.endOffset?.also { document.insertString(it, "\n") } } elements.asReversed().forEach { if (!hasLineBreakBefore(it)) { diff --git a/src/main/kotlin/org/rust/ide/intentions/ListIntention.kt b/src/main/kotlin/org/rust/ide/intentions/ListIntention.kt index b47e328f2e5..d822bee4651 100644 --- a/src/main/kotlin/org/rust/ide/intentions/ListIntention.kt +++ b/src/main/kotlin/org/rust/ide/intentions/ListIntention.kt @@ -9,9 +9,8 @@ import com.intellij.psi.PsiComment import com.intellij.psi.PsiElement import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.util.PsiTreeUtil -import org.rust.lang.core.psi.ext.RsElement -import org.rust.lang.core.psi.ext.leftSiblings -import org.rust.lang.core.psi.ext.rightSiblings +import org.rust.lang.core.psi.RsElementTypes.COMMA +import org.rust.lang.core.psi.ext.* abstract class ListIntentionBase( private val listClass: Class, @@ -31,13 +30,16 @@ abstract class ListIntentionBase( protected val TList.elements: List get() = PsiTreeUtil.getChildrenOfTypeAsList(this, elementClass) - protected fun hasLineBreakAfter(element: TElement): Boolean = nextBreak(element) != null + protected fun hasLineBreakAfter(element: PsiElement): Boolean = nextBreak(element) != null - protected fun nextBreak(element: TElement): PsiWhiteSpace? = element.rightSiblings.lineBreak() + protected fun nextBreak(element: PsiElement): PsiWhiteSpace? = element.rightSiblings.lineBreak() - protected fun hasLineBreakBefore(element: TElement): Boolean = prevBreak(element) != null + protected fun hasLineBreakBefore(element: PsiElement): Boolean = prevBreak(element) != null - protected fun prevBreak(element: TElement): PsiWhiteSpace? = element.leftSiblings.lineBreak() + protected fun prevBreak(element: PsiElement): PsiWhiteSpace? = element.leftSiblings.lineBreak() + + protected fun commaAfter(element: PsiElement): PsiElement? = + element.getNextNonCommentSibling()?.takeIf { it.elementType == COMMA } private fun Sequence.lineBreak(): PsiWhiteSpace? = dropWhile { it !is PsiWhiteSpace && it !is PsiComment } diff --git a/src/test/kotlin/org/rust/ide/intentions/ChopArgumentListIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/ChopArgumentListIntentionTest.kt index 045c03bf819..75dd244f2a4 100644 --- a/src/test/kotlin/org/rust/ide/intentions/ChopArgumentListIntentionTest.kt +++ b/src/test/kotlin/org/rust/ide/intentions/ChopArgumentListIntentionTest.kt @@ -116,7 +116,7 @@ class ChopArgumentListIntentionTest : RsIntentionTestBase(ChopArgumentListIntent 2, 3 // comment 3 ); } - """, """ + """, """ fn foo(p1: i32, p2: i32, p3: i32) {} fn main() { foo( @@ -127,4 +127,35 @@ class ChopArgumentListIntentionTest : RsIntentionTestBase(ChopArgumentListIntent } """) + fun `test trailing comma`() = doAvailableTest(""" + fn foo(p1: i32, p2: i32, p3: i32) {} + fn main() { + foo(/*caret*/1, 2, 3,); + } + """, """ + fn foo(p1: i32, p2: i32, p3: i32) {} + fn main() { + foo( + 1, + 2, + 3, + ); + } + """) + + fun `test trailing comma with comments`() = doAvailableTest(""" + fn foo(p1: i32, p2: i32, p3: i32) {} + fn main() { + foo(/*caret*/1 /* comment 1 */, 2, 3 /* comment 2 */, ); + } + """, """ + fn foo(p1: i32, p2: i32, p3: i32) {} + fn main() { + foo( + 1 /* comment 1 */, + 2, + 3 /* comment 2 */, + ); + } + """) } diff --git a/src/test/kotlin/org/rust/ide/intentions/ChopFieldListIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/ChopFieldListIntentionTest.kt index 9ac901867cb..a641f1cb577 100644 --- a/src/test/kotlin/org/rust/ide/intentions/ChopFieldListIntentionTest.kt +++ b/src/test/kotlin/org/rust/ide/intentions/ChopFieldListIntentionTest.kt @@ -81,7 +81,7 @@ class ChopFieldListIntentionTest : RsIntentionTestBase(ChopFieldListIntention()) /*caret*/x: i32, // comment x y: i32, z: i32 // comment z } - """, """ + """, """ struct S { x: i32, // comment x @@ -89,4 +89,24 @@ class ChopFieldListIntentionTest : RsIntentionTestBase(ChopFieldListIntention()) z: i32 // comment z } """) + + fun `test trailing comma`() = doAvailableTest(""" + struct S { /*caret*/x: i32, y: i32, z: i32, } + """, """ + struct S { + x: i32, + y: i32, + z: i32, + } + """) + + fun `test trailing comma with comments`() = doAvailableTest(""" + struct S { /*caret*/x: i32 /* comment 1 */, y: i32, z: i32 /* comment 2 */, } + """, """ + struct S { + x: i32 /* comment 1 */, + y: i32, + z: i32 /* comment 2 */, + } + """) } diff --git a/src/test/kotlin/org/rust/ide/intentions/ChopParameterListIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/ChopParameterListIntentionTest.kt index 72dd6caef9d..b979d543bc1 100644 --- a/src/test/kotlin/org/rust/ide/intentions/ChopParameterListIntentionTest.kt +++ b/src/test/kotlin/org/rust/ide/intentions/ChopParameterListIntentionTest.kt @@ -80,7 +80,7 @@ class ChopParameterListIntentionTest : RsIntentionTestBase(ChopParameterListInte fn foo(/*caret*/p1: i32, // comment p1 p2: i32, p3: i32 // comment p3 ) {} - """, """ + """, """ fn foo( p1: i32, // comment p1 p2: i32, @@ -88,4 +88,23 @@ class ChopParameterListIntentionTest : RsIntentionTestBase(ChopParameterListInte ) {} """) + fun `test trailing comma`() = doAvailableTest(""" + fn foo(/*caret*/p1: i32, p2: i32, p3: i32,) {} + """, """ + fn foo( + p1: i32, + p2: i32, + p3: i32, + ) {} + """) + + fun `test trailing comma with comments`() = doAvailableTest(""" + fn foo(/*caret*/p1: i32 /* comment 1 */, p2: i32, p3: i32 /* comment 2 */,) {} + """, """ + fn foo( + p1: i32 /* comment 1 */, + p2: i32, + p3: i32 /* comment 2 */, + ) {} + """) } diff --git a/src/test/kotlin/org/rust/ide/intentions/ChopVariantListIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/ChopVariantListIntentionTest.kt index e93755e8a4d..8b8c573c9d4 100644 --- a/src/test/kotlin/org/rust/ide/intentions/ChopVariantListIntentionTest.kt +++ b/src/test/kotlin/org/rust/ide/intentions/ChopVariantListIntentionTest.kt @@ -81,7 +81,7 @@ class ChopVariantListIntentionTest : RsIntentionTestBase(ChopVariantListIntentio /*caret*/A, // comment A B, C // comment C } - """, """ + """, """ enum E { A, // comment A @@ -89,4 +89,24 @@ class ChopVariantListIntentionTest : RsIntentionTestBase(ChopVariantListIntentio C // comment C } """) + + fun `test trailing comma`() = doAvailableTest(""" + enum E { /*caret*/A, B, C, } + """, """ + enum E { + A, + B, + C, + } + """) + + fun `test trailing comma with comments`() = doAvailableTest(""" + enum E { /*caret*/A /* comment 1 */, B, C /* comment 2 */, } + """, """ + enum E { + A /* comment 1 */, + B, + C /* comment 2 */, + } + """) } From 8599491c8c9c916f545238e056e25dfb12446d14 Mon Sep 17 00:00:00 2001 From: Mikhail Chernyavsky Date: Mon, 12 Aug 2019 21:42:47 +0300 Subject: [PATCH 2/3] RUN: Add "Restart" and "Stop" buttons to Cargo build tool window --- .../cargo/CargoBuildConfigurationProvider.kt | 12 +--- .../buildtool/{Utils.kt => UtilsExtra.kt} | 25 +------- .../rust/cargo/runconfig/buildtool/Utils.kt | 51 ---------------- .../cargo/runconfig/buildtool/UtilsExtra.kt | 25 ++++++++ .../runconfig/buildtool/CargoBuildAdapter.kt | 57 ++++++++++++++++-- .../runconfig/buildtool/CargoBuildContext.kt | 2 + .../runconfig/buildtool/CargoBuildManager.kt | 20 +++++++ .../buildtool/CargoBuildTaskProvider.kt | 10 +++- .../buildtool/CargoBuildTaskRunner.kt | 4 +- .../rust/cargo/runconfig/buildtool/Utils.kt | 59 +++++++++++++++++++ 10 files changed, 174 insertions(+), 91 deletions(-) rename src/191/main/kotlin/org/rust/cargo/runconfig/buildtool/{Utils.kt => UtilsExtra.kt} (69%) delete mode 100644 src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt create mode 100644 src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/UtilsExtra.kt create mode 100644 src/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt diff --git a/clion/src/main/kotlin/org/rust/clion/cargo/CargoBuildConfigurationProvider.kt b/clion/src/main/kotlin/org/rust/clion/cargo/CargoBuildConfigurationProvider.kt index 9f29079f34e..d96d8c32f03 100644 --- a/clion/src/main/kotlin/org/rust/clion/cargo/CargoBuildConfigurationProvider.kt +++ b/clion/src/main/kotlin/org/rust/clion/cargo/CargoBuildConfigurationProvider.kt @@ -5,16 +5,11 @@ package org.rust.clion.cargo -import com.intellij.execution.ExecutorRegistry import com.intellij.execution.RunManager -import com.intellij.execution.executors.DefaultRunExecutor import com.intellij.execution.impl.RunManagerImpl -import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl -import com.intellij.execution.runners.ExecutionEnvironment -import com.intellij.execution.runners.ProgramRunner import com.intellij.openapi.project.Project import com.jetbrains.cidr.cpp.execution.build.CLionBuildConfigurationProvider -import org.rust.cargo.runconfig.CargoCommandRunner +import org.rust.cargo.runconfig.buildtool.CargoBuildManager.createBuildEnvironment import org.rust.cargo.runconfig.buildtool.CargoBuildManager.getBuildConfiguration import org.rust.cargo.runconfig.command.CargoCommandConfiguration @@ -24,10 +19,7 @@ class CargoBuildConfigurationProvider : CLionBuildConfigurationProvider { val configuration = runManager.selectedConfiguration?.configuration as? CargoCommandConfiguration ?: return emptyList() val buildConfiguration = getBuildConfiguration(configuration) ?: return emptyList() - val executor = ExecutorRegistry.getInstance().getExecutorById(DefaultRunExecutor.EXECUTOR_ID) - val runner = ProgramRunner.findRunnerById(CargoCommandRunner.RUNNER_ID) ?: return emptyList() - val settings = RunnerAndConfigurationSettingsImpl(runManager, buildConfiguration) - val environment = ExecutionEnvironment(executor, runner, settings, project) + val environment = createBuildEnvironment(buildConfiguration) ?: return emptyList() return listOf(CLionCargoBuildConfiguration(buildConfiguration, environment)) } } diff --git a/src/191/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt b/src/191/main/kotlin/org/rust/cargo/runconfig/buildtool/UtilsExtra.kt similarity index 69% rename from src/191/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt rename to src/191/main/kotlin/org/rust/cargo/runconfig/buildtool/UtilsExtra.kt index 56a3e081dae..0f2d133e669 100644 --- a/src/191/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt +++ b/src/191/main/kotlin/org/rust/cargo/runconfig/buildtool/UtilsExtra.kt @@ -11,6 +11,9 @@ import com.intellij.build.BuildProgressListener import com.intellij.build.events.BuildEvent import com.intellij.build.output.BuildOutputInstantReaderImpl import com.intellij.build.output.BuildOutputParser +import com.intellij.execution.ExecutionListener +import com.intellij.execution.ExecutionManager +import com.intellij.execution.process.ProcessHandler import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.progress.EmptyProgressIndicator import com.intellij.openapi.util.Key @@ -29,13 +32,6 @@ fun BuildOutputInstantReaderImpl.closeAndGetFuture(): CompletableFuture = fun BuildProgressListener.onEvent(parentEventId: Any, event: BuildEvent) = onEvent(event) -typealias CargoPatch = (CargoCommandLine) -> CargoCommandLine - -val ExecutionEnvironment.cargoPatches: MutableList - get() = putUserDataIfAbsent(CARGO_PATCHES, mutableListOf()) - -private val CARGO_PATCHES: Key> = Key.create("CARGO.PATCHES") - object EmptyBuildProgressListener : BuildProgressListener { override fun onEvent(event: BuildEvent) = Unit } @@ -49,18 +45,3 @@ class MockBuildProgressListener : BuildProgressListener { _eventHistory.add(event) } } - -class MockProgressIndicator : EmptyProgressIndicator() { - private val _textHistory: MutableList = mutableListOf() - val textHistory: List get() = _textHistory - - override fun setText(text: String?) { - super.setText(text) - _textHistory += text - } - - override fun setText2(text: String?) { - super.setText2(text) - _textHistory += text - } -} diff --git a/src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt b/src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt deleted file mode 100644 index de26e910988..00000000000 --- a/src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Use of this source code is governed by the MIT license that can be - * found in the LICENSE file. - */ - -@file:Suppress("UnstableApiUsage") - -package org.rust.cargo.runconfig.buildtool - -import com.intellij.build.BuildProgressListener -import com.intellij.build.events.BuildEvent -import com.intellij.execution.runners.ExecutionEnvironment -import com.intellij.openapi.progress.EmptyProgressIndicator -import com.intellij.openapi.util.Key -import org.rust.cargo.toolchain.CargoCommandLine - -typealias CargoPatch = (CargoCommandLine) -> CargoCommandLine - -val ExecutionEnvironment.cargoPatches: MutableList - get() = putUserDataIfAbsent(CARGO_PATCHES, mutableListOf()) - -private val CARGO_PATCHES: Key> = Key.create("CARGO.PATCHES") - -object EmptyBuildProgressListener : BuildProgressListener { - override fun onEvent(buildId: Any, event: BuildEvent) = Unit -} - -class MockProgressIndicator : EmptyProgressIndicator() { - private val _textHistory: MutableList = mutableListOf() - val textHistory: List get() = _textHistory - - override fun setText(text: String?) { - super.setText(text) - _textHistory += text - } - - override fun setText2(text: String?) { - super.setText2(text) - _textHistory += text - } -} - -@Suppress("UnstableApiUsage") -class MockBuildProgressListener : BuildProgressListener { - private val _eventHistory: MutableList = mutableListOf() - val eventHistory: List get() = _eventHistory - - override fun onEvent(buildId: Any, event: BuildEvent) { - _eventHistory.add(event) - } -} diff --git a/src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/UtilsExtra.kt b/src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/UtilsExtra.kt new file mode 100644 index 00000000000..6f2c124c17c --- /dev/null +++ b/src/192/main/kotlin/org/rust/cargo/runconfig/buildtool/UtilsExtra.kt @@ -0,0 +1,25 @@ +/* + * Use of this source code is governed by the MIT license that can be + * found in the LICENSE file. + */ + +@file:Suppress("UnstableApiUsage") + +package org.rust.cargo.runconfig.buildtool + +import com.intellij.build.BuildProgressListener +import com.intellij.build.events.BuildEvent + +object EmptyBuildProgressListener : BuildProgressListener { + override fun onEvent(buildId: Any, event: BuildEvent) = Unit +} + +@Suppress("UnstableApiUsage") +class MockBuildProgressListener : BuildProgressListener { + private val _eventHistory: MutableList = mutableListOf() + val eventHistory: List get() = _eventHistory + + override fun onEvent(buildId: Any, event: BuildEvent) { + _eventHistory.add(event) + } +} diff --git a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildAdapter.kt b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildAdapter.kt index d427162cfab..e34211fe440 100644 --- a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildAdapter.kt +++ b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildAdapter.kt @@ -9,12 +9,20 @@ import com.intellij.build.BuildProgressListener import com.intellij.build.DefaultBuildDescriptor import com.intellij.build.events.impl.* import com.intellij.build.output.BuildOutputInstantReaderImpl -import com.intellij.execution.process.AnsiEscapeDecoder -import com.intellij.execution.process.ProcessAdapter -import com.intellij.execution.process.ProcessEvent -import com.intellij.execution.process.ProcessOutputTypes +import com.intellij.execution.ExecutorRegistry +import com.intellij.execution.actions.StopProcessAction +import com.intellij.execution.impl.ExecutionManagerImpl +import com.intellij.execution.process.* +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.execution.runners.ExecutionUtil +import com.intellij.icons.AllIcons +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.project.DumbAwareAction +import com.intellij.openapi.project.DumbService import com.intellij.openapi.util.Key import com.intellij.openapi.util.SystemInfo +import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VfsUtil import org.rust.cargo.CargoConstants import org.rust.cargo.runconfig.RsAnsiEscapeDecoder @@ -40,6 +48,7 @@ class CargoBuildAdapter( private val textBuffer: MutableList = mutableListOf() init { + context.environment.notifyProcessStarted(context.processHandler) val descriptor = DefaultBuildDescriptor( context.buildId, "Run Cargo command", @@ -48,6 +57,8 @@ class CargoBuildAdapter( ) val buildStarted = StartBuildEventImpl(descriptor, "${context.taskName} running...") .withExecutionFilters(*createFilters(context.cargoProject).toTypedArray()) + .withRestartAction(createRerunAction(context.processHandler, context.environment)) + .withRestartAction(createStopAction(context.processHandler)) buildProgressListener.onEvent(context.buildId, buildStarted) } @@ -72,12 +83,18 @@ class CargoBuildAdapter( buildProgressListener.onEvent(context.buildId, buildFinished) context.finished(isSuccess) + context.environment.notifyProcessTerminated(event.processHandler, event.exitCode) + val targetPath = context.workingDirectory.resolve(CargoConstants.ProjectLayout.target) val targetDir = VfsUtil.findFile(targetPath, true) ?: return@whenComplete VfsUtil.markDirtyAndRefresh(true, true, true, targetDir) } } + override fun processWillTerminate(event: ProcessEvent, willBeDestroyed: Boolean) { + context.environment.notifyProcessTerminating(event.processHandler) + } + override fun onTextAvailable(event: ProcessEvent, outputType: Key<*>) { var rawText = event.text if (SystemInfo.isWindows && rawText.matches(BUILD_PROGRESS_INNER_RE)) { @@ -112,5 +129,37 @@ class CargoBuildAdapter( companion object { private val BUILD_PROGRESS_INNER_RE: Regex = """ \[ *=*>? *] \d+/\d+: [\w\-(.)]+(, [\w\-(.)]+)*""".toRegex() private val BUILD_PROGRESS_FULL_RE: Regex = """ *Building$BUILD_PROGRESS_INNER_RE( *[\r\n])*""".toRegex() + + private fun createStopAction(processHandler: ProcessHandler): StopProcessAction = + StopProcessAction("Stop", "Stop", processHandler) + + private fun createRerunAction(processHandler: ProcessHandler, environment: ExecutionEnvironment): RestartProcessAction = + RestartProcessAction(processHandler, environment) + + private class RestartProcessAction( + private val processHandler: ProcessHandler, + private val environment: ExecutionEnvironment + ) : DumbAwareAction(), AnAction.TransparentUpdate { + private val isEnabled: Boolean + get() { + val project = environment.project + val settings = environment.runnerAndConfigurationSettings + return (!DumbService.isDumb(project) || settings == null || settings.type.isDumbAware) && + !ExecutorRegistry.getInstance().isStarting(environment) && + !processHandler.isProcessTerminating + } + + override fun update(event: AnActionEvent) { + val presentation = event.presentation + presentation.text = "Rerun '${StringUtil.escapeMnemonics(environment.runProfile.name)}'" + presentation.icon = if (processHandler.isProcessTerminated) AllIcons.Actions.Compile else AllIcons.Actions.Restart + presentation.isEnabled = isEnabled + } + + override fun actionPerformed(event: AnActionEvent) { + ExecutionManagerImpl.stopProcess(processHandler) + ExecutionUtil.restart(environment) + } + } } } diff --git a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildContext.kt b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildContext.kt index 24b3593beab..f602eb44c06 100644 --- a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildContext.kt +++ b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildContext.kt @@ -128,6 +128,8 @@ class CargoBuildContext( warnings = warnings, message = "$taskName canceled" )) + + environment.notifyProcessNotStarted() } companion object { diff --git a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildManager.kt b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildManager.kt index 60ae5db0ab0..1b4fe2ec5df 100644 --- a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildManager.kt +++ b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildManager.kt @@ -8,7 +8,14 @@ package org.rust.cargo.runconfig.buildtool import com.intellij.build.BuildContentManager import com.intellij.build.BuildViewManager import com.intellij.execution.ExecutionException +import com.intellij.execution.ExecutorRegistry +import com.intellij.execution.RunManager import com.intellij.execution.configuration.EnvironmentVariablesData +import com.intellij.execution.executors.DefaultRunExecutor +import com.intellij.execution.impl.RunManagerImpl +import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.execution.runners.ProgramRunner import com.intellij.notification.NotificationGroup import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.TransactionGuard @@ -32,6 +39,7 @@ import com.intellij.util.text.SemVer import com.intellij.util.ui.UIUtil import org.jetbrains.annotations.TestOnly import org.rust.cargo.project.model.cargoProjects +import org.rust.cargo.runconfig.CargoCommandRunner import org.rust.cargo.runconfig.CargoRunState import org.rust.cargo.runconfig.addFormatJsonOption import org.rust.cargo.runconfig.command.CargoCommandConfiguration @@ -113,6 +121,7 @@ object CargoBuildManager { context: CargoBuildContext, doExecute: CargoBuildContext.() -> Unit ): FutureResult { + context.environment.notifyProcessStartScheduled() val processCreationLock = Any() when { @@ -160,6 +169,7 @@ object CargoBuildManager { ApplicationManager.getApplication().executeOnPooledThread { if (!context.waitAndStart()) return@executeOnPooledThread + context.environment.notifyProcessStarting() if (isUnitTestMode) { context.doExecute() @@ -218,6 +228,16 @@ object CargoBuildManager { return buildConfiguration } + fun createBuildEnvironment(buildConfiguration: CargoCommandConfiguration): ExecutionEnvironment? { + require(isBuildConfiguration(buildConfiguration)) + val project = buildConfiguration.project + val runManager = RunManager.getInstance(project) as? RunManagerImpl ?: return null + val executor = ExecutorRegistry.getInstance().getExecutorById(DefaultRunExecutor.EXECUTOR_ID) ?: return null + val runner = ProgramRunner.findRunnerById(CargoCommandRunner.RUNNER_ID) ?: return null + val settings = RunnerAndConfigurationSettingsImpl(runManager, buildConfiguration) + return ExecutionEnvironment(executor, runner, settings, project) + } + fun showBuildNotification( project: Project, messageType: MessageType, diff --git a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskProvider.kt b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskProvider.kt index 7cc97665935..354dacf5c15 100644 --- a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskProvider.kt +++ b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskProvider.kt @@ -13,6 +13,7 @@ import com.intellij.icons.AllIcons import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.util.Key import com.intellij.task.ProjectTaskManager +import org.rust.cargo.runconfig.buildtool.CargoBuildManager.createBuildEnvironment import org.rust.cargo.runconfig.buildtool.CargoBuildManager.getBuildConfiguration import org.rust.cargo.runconfig.command.CargoCommandConfiguration import java.util.concurrent.CompletableFuture @@ -30,12 +31,17 @@ class CargoBuildTaskProvider : BeforeRunTaskProvider() ProjectTaskManager.getInstance(configuration.project).build(arrayOf(buildableElement)) { result.complete(it.errors == 0 && !it.isAborted) diff --git a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskRunner.kt b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskRunner.kt index d416b198848..ce185cab1e5 100644 --- a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskRunner.kt +++ b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/CargoBuildTaskRunner.kt @@ -98,9 +98,9 @@ class CargoBuildTaskRunner : ProjectTaskRunner() { return cargoProjects.mapNotNull { cargoProject -> val commandLine = CargoCommandLine.forProject(cargoProject, "build", additionalArguments) val settings = runManager.createCargoCommandRunConfiguration(commandLine) - val executionEnvironment = ExecutionEnvironment(executor, runner, settings, project) + val environment = ExecutionEnvironment(executor, runner, settings, project) val configuration = settings.configuration as? CargoCommandConfiguration ?: return@mapNotNull null - val buildableElement = CargoBuildConfiguration(configuration, executionEnvironment) + val buildableElement = CargoBuildConfiguration(configuration, environment) ProjectModelBuildTaskImpl(buildableElement, false) } } diff --git a/src/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt new file mode 100644 index 00000000000..61e3441cec4 --- /dev/null +++ b/src/main/kotlin/org/rust/cargo/runconfig/buildtool/Utils.kt @@ -0,0 +1,59 @@ +/* + * Use of this source code is governed by the MIT license that can be + * found in the LICENSE file. + */ + +@file:Suppress("UnstableApiUsage") + +package org.rust.cargo.runconfig.buildtool + +import com.intellij.execution.ExecutionListener +import com.intellij.execution.ExecutionManager +import com.intellij.execution.process.ProcessHandler +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.openapi.progress.EmptyProgressIndicator +import com.intellij.openapi.util.Key +import org.rust.cargo.toolchain.CargoCommandLine + +typealias CargoPatch = (CargoCommandLine) -> CargoCommandLine + +val ExecutionEnvironment.cargoPatches: MutableList + get() = putUserDataIfAbsent(CARGO_PATCHES, mutableListOf()) + +private val CARGO_PATCHES: Key> = Key.create("CARGO.PATCHES") + +private val ExecutionEnvironment.executionListener: ExecutionListener + get() = project.messageBus.syncPublisher(ExecutionManager.EXECUTION_TOPIC) + +fun ExecutionEnvironment.notifyProcessStartScheduled() = + executionListener.processStartScheduled(executor.id, this) + +fun ExecutionEnvironment.notifyProcessStarting() = + executionListener.processStarting(executor.id, this) + +fun ExecutionEnvironment.notifyProcessNotStarted() = + executionListener.processNotStarted(executor.id, this) + +fun ExecutionEnvironment.notifyProcessStarted(handler: ProcessHandler) = + executionListener.processStarted(executor.id, this, handler) + +fun ExecutionEnvironment.notifyProcessTerminating(handler: ProcessHandler) = + executionListener.processTerminating(executor.id, this, handler) + +fun ExecutionEnvironment.notifyProcessTerminated(handler: ProcessHandler, exitCode: Int) = + executionListener.processTerminated(executor.id, this, handler, exitCode) + +class MockProgressIndicator : EmptyProgressIndicator() { + private val _textHistory: MutableList = mutableListOf() + val textHistory: List get() = _textHistory + + override fun setText(text: String?) { + super.setText(text) + _textHistory += text + } + + override fun setText2(text: String?) { + super.setText2(text) + _textHistory += text + } +} From 386ab71eb1b41b142e705fe24e5e53a184610d58 Mon Sep 17 00:00:00 2001 From: vlad20012 Date: Mon, 2 Sep 2019 17:06:13 +0300 Subject: [PATCH 3/3] Fix switch to AST when resolving nested macro with the new engine --- .../org/rust/lang/core/macros/RsExpandedElement.kt | 14 ++++++++++++-- .../org/rust/lang/core/resolve/NameResolution.kt | 2 +- .../rust/lang/core/stubs/StubImplementations.kt | 11 +++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/org/rust/lang/core/macros/RsExpandedElement.kt b/src/main/kotlin/org/rust/lang/core/macros/RsExpandedElement.kt index 028a94a0d3d..9d03e54b99b 100644 --- a/src/main/kotlin/org/rust/lang/core/macros/RsExpandedElement.kt +++ b/src/main/kotlin/org/rust/lang/core/macros/RsExpandedElement.kt @@ -6,11 +6,11 @@ package org.rust.lang.core.macros import com.intellij.openapi.util.Key -import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import org.rust.lang.core.psi.RsFile import org.rust.lang.core.psi.RsMacroArgument import org.rust.lang.core.psi.RsMacroCall +import org.rust.lang.core.psi.RsPath import org.rust.lang.core.psi.ext.* import org.rust.lang.core.stubs.index.RsIncludeMacroIndex @@ -144,10 +144,20 @@ private fun PsiElement.findElementExpandedFromNonRecursive(): PsiElement? { } private fun mapOffsetFromExpansionToCallBody(call: RsMacroCall, offset: Int): Int? { + return mapOffsetFromExpansionToCallBodyRelative(call, offset) + ?.fromBodyRelativeOffset(call) +} + +private fun mapOffsetFromExpansionToCallBodyRelative(call: RsMacroCall, offset: Int): Int? { val expansion = call.expansion ?: return null val fileOffset = call.expansionContext.expansionFileStartOffset return expansion.ranges.mapOffsetFromExpansionToCallBody(offset - fileOffset) - ?.fromBodyRelativeOffset(call) +} + +fun PsiElement.cameFromMacroCall(): Boolean { + val call = findMacroCallExpandedFromNonRecursive() ?: return false + val startOffset = (this as? RsPath)?.greenStub?.startOffset ?: startOffset + return mapOffsetFromExpansionToCallBodyRelative(call, startOffset) != null } /** diff --git a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt index d3d216bdc35..72929387a77 100644 --- a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt +++ b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt @@ -718,7 +718,7 @@ fun processMacroCallPathResolveVariants(path: RsPath, isCompletion: Boolean, pro if (isCompletion) { processMacroCallVariantsInScope(path, processor) } else { - if (path.findElementExpandedFrom(strict = false) == null) { + if (!path.cameFromMacroCall()) { // Handles `#[macro_export(local_inner_macros)]` // this "recursive" macro resolve should not be a problem because // 1. we resolve the macro from which [path] is expanded, so it can't run into infinite recursion diff --git a/src/main/kotlin/org/rust/lang/core/stubs/StubImplementations.kt b/src/main/kotlin/org/rust/lang/core/stubs/StubImplementations.kt index 258378db5b1..5d83ea211b5 100644 --- a/src/main/kotlin/org/rust/lang/core/stubs/StubImplementations.kt +++ b/src/main/kotlin/org/rust/lang/core/stubs/StubImplementations.kt @@ -36,7 +36,7 @@ class RsFileStub : PsiFileStubImpl { object Type : IStubFileElementType(RsLanguage) { // Bump this number if Stub structure changes - override fun getStubVersion(): Int = 179 + override fun getStubVersion(): Int = 180 override fun getBuilder(): StubBuilder = object : DefaultStubBuilder() { override fun createStubForFile(file: PsiFile): StubElement<*> = RsFileStub(file as RsFile) @@ -719,7 +719,8 @@ class RsPathStub( parent: StubElement<*>?, elementType: IStubElementType<*, *>, val referenceName: String, val hasColonColon: Boolean, - val kind: PathKind + val kind: PathKind, + val startOffset: Int ) : StubBase(parent, elementType) { object Type : RsStubElementType("PATH") { @@ -729,13 +730,14 @@ class RsPathStub( RsPathImpl(stub, this) override fun createStub(psi: RsPath, parentStub: StubElement<*>?) = - RsPathStub(parentStub, this, psi.referenceName, psi.hasColonColon, psi.kind) + RsPathStub(parentStub, this, psi.referenceName, psi.hasColonColon, psi.kind, psi.startOffset) override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?) = RsPathStub(parentStub, this, dataStream.readName()!!.string, dataStream.readBoolean(), - dataStream.readEnum() + dataStream.readEnum(), + dataStream.readVarInt() ) override fun serialize(stub: RsPathStub, dataStream: StubOutputStream) = @@ -743,6 +745,7 @@ class RsPathStub( writeName(stub.referenceName) writeBoolean(stub.hasColonColon) writeEnum(stub.kind) + writeVarInt(stub.startOffset) } } }