From 71aadc38c61979a4fd725e78753e6deafbbf76e0 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Tue, 14 Jan 2025 15:55:43 +0100 Subject: [PATCH 1/9] Wrap `runnable` with `try-catch` before passing to PSI --- .../io/spine/tools/psi/java/PsiCommands.kt | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt index b5d4720f..7552e9c7 100644 --- a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt +++ b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt @@ -29,6 +29,7 @@ package io.spine.tools.psi.java import com.intellij.openapi.command.CommandProcessor import io.spine.tools.psi.java.Environment.commandProcessor import io.spine.tools.psi.java.Environment.project +import java.lang.Thread.getDefaultUncaughtExceptionHandler /** * Executes the given [Runnable] as a PSI modification @@ -36,5 +37,37 @@ import io.spine.tools.psi.java.Environment.project */ @JvmName("execute") public fun execute(runnable: Runnable) { - commandProcessor.executeCommand(project, runnable, null, null) + val command = withRedirectedErrors(runnable) + commandProcessor.executeCommand(project, command, null, null) +} + +/** + * Wraps the given [runnable] in a try-catch block, redirecting any [Throwable] + * to the default uncaught exception handler. + * + * The `CoreCommandProcessor` used by PSI for command handling swallows any + * [Throwable] from the passed [Runnable]. As a result, PSI users cannot know + * if an error has occurred. For example, ProtoData is expected to print + * the stacktrace and exist the application in case of error or exception, + * but this behavior is suppressed by PSI. + * + * This method addresses this issue by wrapping the given [runnable] in its own + * try-catch block, redirecting all errors and exceptions to the default handler. + * This ensures that PSI does not swallow these exceptions. However, as a consequence, + * the default exception handler must be explicitly set, as redirection only works + * when an explicit handler is in place. + * + * Note: to make this method work, the default exception handler must be set explicitly + * using [Thread.setDefaultUncaughtExceptionHandler]. Otherwise, a [NullPointerException] + * will be thrown and swallowed by PSI, making this method ineffective. + */ +@Suppress("TooGenericExceptionCaught") +private fun withRedirectedErrors(runnable: Runnable) = Runnable { + try { + runnable.run() + } catch (e: Throwable) { + val currentThread = Thread.currentThread() + val globalHandler = getDefaultUncaughtExceptionHandler() + globalHandler.uncaughtException(currentThread, e) + } } From 521afe1b200b77db5b8ec9d86523d0a7b80e6098 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Tue, 14 Jan 2025 15:58:40 +0100 Subject: [PATCH 2/9] Bump the version -> `2.0.0-SNAPSHOT.241` --- version.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.gradle.kts b/version.gradle.kts index 39eb3c79..3e8094c8 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -24,4 +24,4 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -val versionToPublish: String by extra("2.0.0-SNAPSHOT.240") +val versionToPublish: String by extra("2.0.0-SNAPSHOT.241") From 124eb6fee9edd17ab0937123686c2967ea993697 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Tue, 14 Jan 2025 15:58:51 +0100 Subject: [PATCH 3/9] Update reports --- dependencies.md | 28 ++++++++++++++-------------- pom.xml | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dependencies.md b/dependencies.md index b208f29b..bb3384e0 100644 --- a/dependencies.md +++ b/dependencies.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine.tools:intellij-platform:2.0.0-SNAPSHOT.240` +# Dependencies of `io.spine.tools:intellij-platform:2.0.0-SNAPSHOT.241` ## Runtime 1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3. @@ -493,12 +493,12 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sun Dec 15 16:11:25 WET 2024** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue Jan 14 15:55:52 CET 2025** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:intellij-platform-java:2.0.0-SNAPSHOT.240` +# Dependencies of `io.spine.tools:intellij-platform-java:2.0.0-SNAPSHOT.241` ## Runtime 1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3. @@ -1752,12 +1752,12 @@ This report was generated on **Sun Dec 15 16:11:25 WET 2024** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sun Dec 15 16:11:25 WET 2024** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue Jan 14 15:55:52 CET 2025** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-plugin-base:2.0.0-SNAPSHOT.240` +# Dependencies of `io.spine.tools:spine-plugin-base:2.0.0-SNAPSHOT.241` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -2505,12 +2505,12 @@ This report was generated on **Sun Dec 15 16:11:25 WET 2024** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sun Dec 15 16:11:26 WET 2024** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue Jan 14 15:55:53 CET 2025** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-plugin-testlib:2.0.0-SNAPSHOT.240` +# Dependencies of `io.spine.tools:spine-plugin-testlib:2.0.0-SNAPSHOT.241` ## Runtime 1. **Group** : com.google.auto.value. **Name** : auto-value-annotations. **Version** : 1.10.2. @@ -3373,12 +3373,12 @@ This report was generated on **Sun Dec 15 16:11:26 WET 2024** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sun Dec 15 16:11:26 WET 2024** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue Jan 14 15:55:53 CET 2025** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-psi:2.0.0-SNAPSHOT.240` +# Dependencies of `io.spine.tools:spine-psi:2.0.0-SNAPSHOT.241` ## Runtime 1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3. @@ -4380,12 +4380,12 @@ This report was generated on **Sun Dec 15 16:11:26 WET 2024** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sun Dec 15 16:11:26 WET 2024** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue Jan 14 15:55:53 CET 2025** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-psi-java:2.0.0-SNAPSHOT.240` +# Dependencies of `io.spine.tools:spine-psi-java:2.0.0-SNAPSHOT.241` ## Runtime 1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3. @@ -6065,12 +6065,12 @@ This report was generated on **Sun Dec 15 16:11:26 WET 2024** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sun Dec 15 16:11:27 WET 2024** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue Jan 14 15:55:54 CET 2025** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-tool-base:2.0.0-SNAPSHOT.240` +# Dependencies of `io.spine.tools:spine-tool-base:2.0.0-SNAPSHOT.241` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -6867,4 +6867,4 @@ This report was generated on **Sun Dec 15 16:11:27 WET 2024** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sun Dec 15 16:11:27 WET 2024** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file +This report was generated on **Tue Jan 14 15:55:54 CET 2025** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6d1d3a3f..d2044558 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject. --> io.spine.tools tool-base -2.0.0-SNAPSHOT.240 +2.0.0-SNAPSHOT.241 2015 From d7a9cdc8eb7f39b123dbe60f4ed6cf01ddc0da03 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Tue, 14 Jan 2025 18:00:13 +0100 Subject: [PATCH 4/9] Make `execute()` handle errors by default --- .../io/spine/tools/psi/java/PsiCommands.kt | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt index 7552e9c7..d04cac57 100644 --- a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt +++ b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt @@ -29,45 +29,50 @@ package io.spine.tools.psi.java import com.intellij.openapi.command.CommandProcessor import io.spine.tools.psi.java.Environment.commandProcessor import io.spine.tools.psi.java.Environment.project -import java.lang.Thread.getDefaultUncaughtExceptionHandler +import kotlin.system.exitProcess /** - * Executes the given [Runnable] as a PSI modification - * [command][CommandProcessor.executeCommand]. + * Executes the given [runnable] as a PSI modification [command][CommandProcessor.executeCommand], + * ensuring any errors thrown by the [runnable] are not ignored. + * + * By default, the `CoreCommandProcessor` used for PSI command processing suppresses + * any [Throwable] thrown by the passed command, making it difficult for PSI users + * to detect and handle errors. + * + * To mitigate it, this method wraps the given [runnable] in a try-catch block. + * Any thrown errors or exceptions are logged to [System.err], and the process + * terminates with a non-zero exit code. If this behavior is not desired, + * use [executeSilent], which leaves error handling to the `CoreCommandProcessor` + * or the [runnable] itself. + * + * @see executeSilent */ @JvmName("execute") public fun execute(runnable: Runnable) { - val command = withRedirectedErrors(runnable) - commandProcessor.executeCommand(project, command, null, null) + val withCaughtErrors = Runnable { + try { + runnable.run() + } catch (e: Throwable) { + e.printStackTrace() // Logs to `System.err`. + exitProcess(1) // Non-zero value indicates a general error. + } + } + executeSilent(withCaughtErrors) } /** - * Wraps the given [runnable] in a try-catch block, redirecting any [Throwable] - * to the default uncaught exception handler. + * Executes the given [runnable] as a PSI modification [command][CommandProcessor.executeCommand], + * ignoring any errors thrown by the [runnable]. * - * The `CoreCommandProcessor` used by PSI for command handling swallows any - * [Throwable] from the passed [Runnable]. As a result, PSI users cannot know - * if an error has occurred. For example, ProtoData is expected to print - * the stacktrace and exist the application in case of error or exception, - * but this behavior is suppressed by PSI. + * Any exceptions or errors thrown by the given [runnable] are caught and ignored + * with no logging or further actions. * - * This method addresses this issue by wrapping the given [runnable] in its own - * try-catch block, redirecting all errors and exceptions to the default handler. - * This ensures that PSI does not swallow these exceptions. However, as a consequence, - * the default exception handler must be explicitly set, as redirection only works - * when an explicit handler is in place. + * This method is suitable for use cases where error handling is either unnecessary + * or managed directly by the [runnable] itself. * - * Note: to make this method work, the default exception handler must be set explicitly - * using [Thread.setDefaultUncaughtExceptionHandler]. Otherwise, a [NullPointerException] - * will be thrown and swallowed by PSI, making this method ineffective. + * @see execute */ -@Suppress("TooGenericExceptionCaught") -private fun withRedirectedErrors(runnable: Runnable) = Runnable { - try { - runnable.run() - } catch (e: Throwable) { - val currentThread = Thread.currentThread() - val globalHandler = getDefaultUncaughtExceptionHandler() - globalHandler.uncaughtException(currentThread, e) - } +@JvmName("executeSilent") +public fun executeSilent(runnable: Runnable) { + commandProcessor.executeCommand(project, runnable, null, null) } From 25cb87c3b3edb7fbf7de530ed3bdb6999ed11e00 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Tue, 14 Jan 2025 18:11:16 +0100 Subject: [PATCH 5/9] Suppress Detekt warning --- psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt index d04cac57..939db1e1 100644 --- a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt +++ b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt @@ -48,6 +48,7 @@ import kotlin.system.exitProcess * @see executeSilent */ @JvmName("execute") +@Suppress("TooGenericExceptionCaught") // `CoreCommandProcessor` also catches `Throwable`. public fun execute(runnable: Runnable) { val withCaughtErrors = Runnable { try { From b1bcda7cf7ddba3bf18a4856a7b5cc61d21f660c Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Tue, 14 Jan 2025 18:25:57 +0100 Subject: [PATCH 6/9] Pass handler as a parameter --- .../io/spine/tools/psi/java/PsiCommands.kt | 51 +++++++++++-------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt index 939db1e1..b188b031 100644 --- a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt +++ b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt @@ -33,43 +33,54 @@ import kotlin.system.exitProcess /** * Executes the given [runnable] as a PSI modification [command][CommandProcessor.executeCommand], - * ensuring any errors thrown by the [runnable] are not ignored. + * ensuring any errors thrown by the [runnable] are handled with the provided [errorHandler]. * * By default, the `CoreCommandProcessor` used for PSI command processing suppresses - * any [Throwable] thrown by the passed command, making it difficult for PSI users - * to detect and handle errors. + * any [Throwable] thrown by the command, making it difficult for PSI users to detect + * and handle errors. * - * To mitigate it, this method wraps the given [runnable] in a try-catch block. - * Any thrown errors or exceptions are logged to [System.err], and the process - * terminates with a non-zero exit code. If this behavior is not desired, - * use [executeSilent], which leaves error handling to the `CoreCommandProcessor` - * or the [runnable] itself. + * To address it, this method wraps the given [runnable] in a try-catch block. + * Any thrown errors or exceptions are passed to the provided [errorHandler]. + * + * If no custom [errorHandler] is provided, the default behavior is to log the error + * to [System.err] and terminates the process with a non-zero exit code. + * Use [executeSilent] to suppress errors entirely. + * + * @param runnable The [Runnable] to execute as a PSI modification. + * @param errorHandler A lambda to handle any [Throwable] thrown by the [runnable]. + * Default to logging the error and terminating the process. * * @see executeSilent */ @JvmName("execute") -@Suppress("TooGenericExceptionCaught") // `CoreCommandProcessor` also catches `Throwable`. -public fun execute(runnable: Runnable) { - val withCaughtErrors = Runnable { +@Suppress("TooGenericExceptionCaught") // We need everything, including `java.lang.Error`. +public fun execute(runnable: Runnable, errorHandler: (Throwable) -> Unit = ::logAndTerminate) { + val withHandledErrors = Runnable { try { runnable.run() - } catch (e: Throwable) { - e.printStackTrace() // Logs to `System.err`. - exitProcess(1) // Non-zero value indicates a general error. + } catch (t: Throwable) { + errorHandler(t) } } - executeSilent(withCaughtErrors) + executeSilent(withHandledErrors) +} + +/** + * The default error handler for [execute] that logs the given [Throwable] to [System.err] + * and terminates the currently running process with a non-zero exit code. + */ +private fun logAndTerminate(t: Throwable) { + t.printStackTrace() + exitProcess(1) } /** * Executes the given [runnable] as a PSI modification [command][CommandProcessor.executeCommand], - * ignoring any errors thrown by the [runnable]. + * suppressing any errors thrown by the [runnable]. * * Any exceptions or errors thrown by the given [runnable] are caught and ignored - * with no logging or further actions. - * - * This method is suitable for use cases where error handling is either unnecessary - * or managed directly by the [runnable] itself. + * with no logging or further action. This method is suitable for use cases where error + * handling is either unnecessary or managed by the [runnable] itself. * * @see execute */ From e78ae0e174fdd6656416f670cca1680f89a73c16 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Tue, 14 Jan 2025 18:35:20 +0100 Subject: [PATCH 7/9] Change parameter order --- psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt index b188b031..7e5fbaf9 100644 --- a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt +++ b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt @@ -54,7 +54,7 @@ import kotlin.system.exitProcess */ @JvmName("execute") @Suppress("TooGenericExceptionCaught") // We need everything, including `java.lang.Error`. -public fun execute(runnable: Runnable, errorHandler: (Throwable) -> Unit = ::logAndTerminate) { +public fun execute(errorHandler: (Throwable) -> Unit = ::logAndTerminate, runnable: Runnable) { val withHandledErrors = Runnable { try { runnable.run() From a88e19db797c2aa9d0481fba3c96599c647dd4c4 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Wed, 15 Jan 2025 11:31:59 +0100 Subject: [PATCH 8/9] Apply `@JvmOverloads` annotation --- psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt index 7e5fbaf9..a41ab922 100644 --- a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt +++ b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt @@ -52,6 +52,7 @@ import kotlin.system.exitProcess * * @see executeSilent */ +@JvmOverloads @JvmName("execute") @Suppress("TooGenericExceptionCaught") // We need everything, including `java.lang.Error`. public fun execute(errorHandler: (Throwable) -> Unit = ::logAndTerminate, runnable: Runnable) { From 3281833f952d4498fbbccc4507c95a69dc13a162 Mon Sep 17 00:00:00 2001 From: yevhenii-nadtochii Date: Wed, 15 Jan 2025 12:01:42 +0100 Subject: [PATCH 9/9] Remove `executeSilent()` --- .../io/spine/tools/psi/java/PsiCommands.kt | 38 ++++--------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt index a41ab922..0005d1bd 100644 --- a/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt +++ b/psi-java/src/main/kotlin/io/spine/tools/psi/java/PsiCommands.kt @@ -33,29 +33,26 @@ import kotlin.system.exitProcess /** * Executes the given [runnable] as a PSI modification [command][CommandProcessor.executeCommand], - * ensuring any errors thrown by the [runnable] are handled with the provided [errorHandler]. + * ensuring any errors thrown by the [runnable] are handled using the provided [errorHandler]. * * By default, the `CoreCommandProcessor` used for PSI command processing suppresses * any [Throwable] thrown by the command, making it difficult for PSI users to detect * and handle errors. * - * To address it, this method wraps the given [runnable] in a try-catch block. + * To address this, the given [runnable] is wrapped in a try-catch block. * Any thrown errors or exceptions are passed to the provided [errorHandler]. * - * If no custom [errorHandler] is provided, the default behavior is to log the error - * to [System.err] and terminates the process with a non-zero exit code. - * Use [executeSilent] to suppress errors entirely. + * If no custom [errorHandler] is provided, the default behavior is to print the stack + * trace to [System.err] and terminate the process with the exit code `1`. * * @param runnable The [Runnable] to execute as a PSI modification. * @param errorHandler A lambda to handle any [Throwable] thrown by the [runnable]. - * Default to logging the error and terminating the process. - * - * @see executeSilent + * Defaults to printing the stack trace and terminating the process with the exit code `1`. */ @JvmOverloads @JvmName("execute") @Suppress("TooGenericExceptionCaught") // We need everything, including `java.lang.Error`. -public fun execute(errorHandler: (Throwable) -> Unit = ::logAndTerminate, runnable: Runnable) { +public fun execute(errorHandler: (Throwable) -> Unit = ::printAndTerminate, runnable: Runnable) { val withHandledErrors = Runnable { try { runnable.run() @@ -63,29 +60,10 @@ public fun execute(errorHandler: (Throwable) -> Unit = ::logAndTerminate, runnab errorHandler(t) } } - executeSilent(withHandledErrors) + commandProcessor.executeCommand(project, withHandledErrors, null, null) } -/** - * The default error handler for [execute] that logs the given [Throwable] to [System.err] - * and terminates the currently running process with a non-zero exit code. - */ -private fun logAndTerminate(t: Throwable) { +private fun printAndTerminate(t: Throwable) { t.printStackTrace() exitProcess(1) } - -/** - * Executes the given [runnable] as a PSI modification [command][CommandProcessor.executeCommand], - * suppressing any errors thrown by the [runnable]. - * - * Any exceptions or errors thrown by the given [runnable] are caught and ignored - * with no logging or further action. This method is suitable for use cases where error - * handling is either unnecessary or managed by the [runnable] itself. - * - * @see execute - */ -@JvmName("executeSilent") -public fun executeSilent(runnable: Runnable) { - commandProcessor.executeCommand(project, runnable, null, null) -}