Conversation
| <component name="ProjectRunConfigurationManager"> | ||
| <configuration default="false" name="Run Plugin" type="GradleRunConfiguration" factoryName="Gradle"> | ||
| <log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" /> | ||
| <log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/IC-*/log/idea.log" /> |
eeafa92 to
33d3067
Compare
.github/workflows/pre-merge.yaml
Outdated
| uses: actions/checkout@v2 | ||
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Setup Java | ||
| uses: actions/setup-java@v3 | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| distribution: 'zulu' | ||
| java-version: ${{ matrix.jdk }} | ||
| - name: Setup Gradle | ||
| uses: gradle/actions/setup-gradle@v5 | ||
|
|
||
| - name: Build detekt idea plugin | ||
| uses: gradle/gradle-build-action@v2 | ||
| with: | ||
| arguments: build --no-daemon | ||
| run: ./gradlew build |
There was a problem hiding this comment.
The checks failed on Windows for some reason, took the opportunity to updae the actions setup
33d3067 to
dc4a387
Compare
|
@arturbosch can you review this one? |
|
Yes, I will have some time on the weekend. Sorry for the delay. |
There was a problem hiding this comment.
Pull request overview
This PR introduces a sophisticated Maven-based plugin management system for the Detekt IntelliJ plugin, allowing users to discover, download, and manage third-party rule sets directly from Maven repositories within the IDE. The implementation replaces manual JAR file handling with automatic dependency resolution, transitive dependency management, and a project-local storage system (.idea/detektPlugins/).
Changes:
- Added Maven-based plugin resolution with automatic dependency management
- Implemented UI for searching Maven artifacts and customizing transitive dependencies
- Updated platform requirements to IntelliJ 2024.2 (build 242) and JVM 21
- Added comprehensive test coverage for dependency resolution, cycle detection, and exclusion logic
Reviewed changes
Copilot reviewed 38 out of 40 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| ProvidedDependenciesTest.kt | Tests for identifying dependencies provided by the platform (detekt-api, kotlin-stdlib, etc.) |
| PluginDependencyServiceTest.kt | Tests for plugin lifecycle management including filtering, exclusions, and cycle handling |
| MavenDependencyResolverTest.kt | Tests for Maven coordinate parsing and dependency tree resolution |
| MavenArtifactFetcherTest.kt | Tests for Maven artifact search, version fetching, and GAV parsing |
| DependencySelectionHandlerTest.kt | Tests for checkbox synchronization logic in the dependency tree UI |
| DependencyCycleTest.kt | Tests for handling cyclic dependencies without stack overflow |
| PluginDependencyService.kt | Core service orchestrating plugin download, reconciliation, and cleanup |
| MavenDependencyResolver.kt | Resolves Maven coordinates to full dependency trees with cycle detection |
| MavenTreeResolver.kt | Low-level interface to IntelliJ's Maven infrastructure |
| MavenSearchDialog.kt | UI for searching, selecting versions, and previewing dependencies |
| DependencyExclusionEditor.kt | Tree-based editor for excluding transitive dependencies |
| DetektPluginSettings.kt | Updated to persist Maven plugin configurations and trigger reconciliation |
| ConfiguredService.kt | Modified to include downloaded Maven plugins in classpath |
| plugin.xml | Added Maven module dependency and updated minimum platform version |
| build.gradle.kts | Updated to IntelliJ 2024.2 and JVM 21 with kotlinx exclusions |
| DETEKT_PLUGINS.md | Comprehensive documentation of architecture and data flow |
| .github/workflows/pre-merge.yaml | Updated GitHub Actions versions |
Files not reviewed (1)
- .idea/detekt.xml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/DetektPluginSettings.kt
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/util/MavenDependencyResolver.kt
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/MavenArtifactFetcher.kt
Show resolved
Hide resolved
dc4a387 to
819cfb7
Compare
|
Build failed due to some silly dependency resolution issue on one of the platforms, please restart it |
There was a problem hiding this comment.
Thanks for the really cool feature!
This is the first batch of comments. I will continue tomorrow.
btw just found out that we need to opt in for K2 in the plugin:
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<supportsKotlinPluginMode supportsK2="true" />
</extensions>
Seems to work on the first go but not sure if the K1 classes will be deleted in a future release.
For me, resolving detekt-formatting hangs unfortunately:

Stacktraces:
2026-02-08 23:12:34,252 [ 623479] INFO - #c.i.j.s.MavenRepositoryServicesManager - com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 401. Status=401, Url=https://oss.sonatype.org/service/local/search/gavc?g=detekt-&repos=
java.io.IOException: com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 401. Status=401, Url=https://oss.sonatype.org/service/local/search/gavc?g=detekt-&repos=
at com.intellij.jarRepository.services.artifactory.ArtifactoryRepositoryService.findArtifacts(ArtifactoryRepositoryService.java:82)
at com.intellij.jarRepository.services.MavenRepositoryServicesManager.findArtifacts(MavenRepositoryServicesManager.java:95)
at com.intellij.jarRepository.JarRepositoryManager$3.run(JarRepositoryManager.java:467)
at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:534)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:180)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsynchronously$7(CoreProgressManager.java:585)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:268)
at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:98)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$1(CoreProgressManager.java:260)
at com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.use(trace.kt:44)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:259)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$14(CoreProgressManager.java:717)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:792)
at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:748)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:716)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:75)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:240)
at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:98)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$5(ProgressRunner.java:268)
at com.intellij.openapi.progress.impl.ProgressRunner$ProgressRunnable.run(ProgressRunner.java:546)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$18(ProgressRunner.java:501)
at com.intellij.concurrency.ThreadContext.installThreadContext(threadContext.kt:305)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$19(ProgressRunner.java:500)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:173)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:167)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$20(ProgressRunner.java:497)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:735)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:732)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:732)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 401. Status=401, Url=https://oss.sonatype.org/service/local/search/gavc?g=detekt-&repos=
at com.intellij.util.io.HttpRequests.throwHttpStatusError(HttpRequests.java:709)
at com.intellij.util.io.HttpRequests.openConnection(HttpRequests.java:672)
at com.intellij.util.io.HttpRequests$RequestImpl.getConnection(HttpRequests.java:381)
at com.intellij.util.io.HttpRequests$RequestImpl.doReadBytes(HttpRequests.java:457)
at com.intellij.util.io.HttpRequests$RequestImpl.readString(HttpRequests.java:446)
at com.intellij.util.io.RequestBuilder.lambda$readString$5(RequestBuilder.java:86)
at com.intellij.util.io.HttpRequests.doProcess(HttpRequests.java:544)
at com.intellij.util.io.HttpRequests.process(HttpRequests.java:526)
at com.intellij.util.io.HttpRequests$RequestBuilderImpl.connect(HttpRequests.java:355)
at com.intellij.util.io.RequestBuilder.readString(RequestBuilder.java:86)
at com.intellij.util.io.RequestBuilder.readString(RequestBuilder.java:90)
at com.intellij.jarRepository.services.artifactory.ArtifactoryRepositoryService.searchArtifacts(ArtifactoryRepositoryService.java:126)
at com.intellij.jarRepository.services.artifactory.ArtifactoryRepositoryService.findArtifacts(ArtifactoryRepositoryService.java:72)
... 34 more
2026-02-08 23:12:35,849 [ 625076] INFO - #c.i.j.s.MavenRepositoryServicesManager - com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 404. Status=404, Url=https://repository.jboss.org/nexus/service/local/data_index?q=detekt-&g=detekt-
java.io.IOException: com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 404. Status=404, Url=https://repository.jboss.org/nexus/service/local/data_index?q=detekt-&g=detekt-
at com.intellij.jarRepository.services.nexus.NexusRepositoryService.findArtifacts(NexusRepositoryService.java:106)
at com.intellij.jarRepository.services.MavenRepositoryServicesManager.findArtifacts(MavenRepositoryServicesManager.java:95)
at com.intellij.jarRepository.JarRepositoryManager$3.run(JarRepositoryManager.java:467)
at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:534)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:180)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsynchronously$7(CoreProgressManager.java:585)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:268)
at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:98)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$1(CoreProgressManager.java:260)
at com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.use(trace.kt:44)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:259)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$14(CoreProgressManager.java:717)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:792)
at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:748)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:716)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:75)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:240)
at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:98)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$5(ProgressRunner.java:268)
at com.intellij.openapi.progress.impl.ProgressRunner$ProgressRunnable.run(ProgressRunner.java:546)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$18(ProgressRunner.java:501)
at com.intellij.concurrency.ThreadContext.installThreadContext(threadContext.kt:305)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$19(ProgressRunner.java:500)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:173)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:167)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$20(ProgressRunner.java:497)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:735)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:732)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:732)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 404. Status=404, Url=https://repository.jboss.org/nexus/service/local/data_index?q=detekt-&g=detekt-
at com.intellij.util.io.HttpRequests.throwHttpStatusError(HttpRequests.java:709)
at com.intellij.util.io.HttpRequests.openConnection(HttpRequests.java:672)
at com.intellij.util.io.HttpRequests$RequestImpl.getConnection(HttpRequests.java:381)
at com.intellij.util.io.HttpRequests$RequestImpl.doReadBytes(HttpRequests.java:457)
at com.intellij.util.io.HttpRequests$RequestImpl.readString(HttpRequests.java:446)
at com.intellij.util.io.RequestBuilder.lambda$readString$5(RequestBuilder.java:86)
at com.intellij.util.io.HttpRequests.doProcess(HttpRequests.java:544)
at com.intellij.util.io.HttpRequests.process(HttpRequests.java:526)
at com.intellij.util.io.HttpRequests$RequestBuilderImpl.connect(HttpRequests.java:355)
at com.intellij.util.io.RequestBuilder.readString(RequestBuilder.java:86)
at com.intellij.util.io.RequestBuilder.readString(RequestBuilder.java:90)
at com.intellij.jarRepository.services.nexus.NexusRepositoryService.findArtifacts(NexusRepositoryService.java:89)
... 34 more
2026-02-08 23:12:36,268 [ 625495] INFO - #c.i.j.s.MavenRepositoryServicesManager - com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 400. Status=400, Url=https://repository.jboss.org/nexus/service/local/search/gavc?g=detekt-&repos=
java.io.IOException: com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 400. Status=400, Url=https://repository.jboss.org/nexus/service/local/search/gavc?g=detekt-&repos=
at com.intellij.jarRepository.services.artifactory.ArtifactoryRepositoryService.findArtifacts(ArtifactoryRepositoryService.java:82)
at com.intellij.jarRepository.services.MavenRepositoryServicesManager.findArtifacts(MavenRepositoryServicesManager.java:95)
at com.intellij.jarRepository.JarRepositoryManager$3.run(JarRepositoryManager.java:467)
at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:534)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:180)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsynchronously$7(CoreProgressManager.java:585)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:268)
at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:98)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$1(CoreProgressManager.java:260)
at com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.use(trace.kt:44)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:259)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$14(CoreProgressManager.java:717)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:792)
at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:748)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:716)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:75)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:240)
at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:98)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$5(ProgressRunner.java:268)
at com.intellij.openapi.progress.impl.ProgressRunner$ProgressRunnable.run(ProgressRunner.java:546)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$18(ProgressRunner.java:501)
at com.intellij.concurrency.ThreadContext.installThreadContext(threadContext.kt:305)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$19(ProgressRunner.java:500)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:173)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:167)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$20(ProgressRunner.java:497)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:735)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:732)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:732)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: com.intellij.util.io.HttpRequests$HttpStatusException: Request failed with status code 400. Status=400, Url=https://repository.jboss.org/nexus/service/local/search/gavc?g=detekt-&repos=
at com.intellij.util.io.HttpRequests.throwHttpStatusError(HttpRequests.java:709)
at com.intellij.util.io.HttpRequests.openConnection(HttpRequests.java:672)
at com.intellij.util.io.HttpRequests$RequestImpl.getConnection(HttpRequests.java:381)
at com.intellij.util.io.HttpRequests$RequestImpl.doReadBytes(HttpRequests.java:457)
at com.intellij.util.io.HttpRequests$RequestImpl.readString(HttpRequests.java:446)
at com.intellij.util.io.RequestBuilder.lambda$readString$5(RequestBuilder.java:86)
at com.intellij.util.io.HttpRequests.doProcess(HttpRequests.java:544)
at com.intellij.util.io.HttpRequests.process(HttpRequests.java:526)
at com.intellij.util.io.HttpRequests$RequestBuilderImpl.connect(HttpRequests.java:355)
at com.intellij.util.io.RequestBuilder.readString(RequestBuilder.java:86)
at com.intellij.util.io.RequestBuilder.readString(RequestBuilder.java:90)
at com.intellij.jarRepository.services.artifactory.ArtifactoryRepositoryService.searchArtifacts(ArtifactoryRepositoryService.java:126)
at com.intellij.jarRepository.services.artifactory.ArtifactoryRepositoryService.findArtifacts(ArtifactoryRepositoryService.java:72)
... 34 more
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/logic/SyncableNode.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/DependencyExclusionEditor.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/DependencyExclusionEditor.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/DependencyExclusionEditor.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/DetektConfigUi.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/MavenArtifactFetcher.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/MavenArtifactFetcher.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/io/gitlab/arturbosch/detekt/idea/config/ui/MavenSearchDialog.kt
Outdated
Show resolved
Hide resolved
|
I think the issue you were seeing was backend related — the 404s are expected when the search returns nothing, the 401 is weird and probably some transient issue. I am adding a bunch of extra logic and tests to improve error handling, anyway. |
This commit introduces a system for managing detekt plugins directly from the IDE, allowing users to add third-party rule sets from Maven repositories with automatic transitive dependency resolution. Architectural highlights: - Plugin Infrastructure: introduced `PluginDependencyService` to orchestrate the lifecycle of plugin JARs. Plugins are now stored in a project-local folder (`.idea/detektPlugins/`) and tracked via a state file, `downloaded.json`. - Maven Integration: using IntelliJ's internal Maven infrastructure (via `JarRepositoryManager` and `ArtifactRepositoryManager`), we can now reliably discover and resolve detekt plugin artefacts, through the new `MavenDependencyResolver` and `MavenArtifactFetcher`. - Automatic Reconciliation: implemented a synchronization mechanism that ensures the local plugin folder matches the current project configuration. This runs as a background task on settings apply, project open, or VCS-triggered state reloads. - Dependency Exclusion UI: added an interactive `DependencyExclusionEditor` that allows users to selectively exclude transitive dependencies if they so wish. It includes smart propagation rules via `DependencySelectionHandler` and the "provided" dependency protection to prevent classpath conflicts with the IDE runtime. - Analysis Integration: `ConfiguredService` now dynamically discovers and includes downloaded JARs in the detekt analysis classpath, ensuring that third-party rules are applied immediately after they are downloaded. Main components: - `PluginDependencyService`: Project service for JAR lifecycle, reconciliation, and cleanup. - `MavenSearchDialog`: new UI for free text or GAV-based search, version selection, and transitive dependency exclusion. - `DependencyExclusionEditor`: checkbox-tree interface for transitive dependency management. Forked from JPS' own (private) equivalent UI. - `DETEKT_PLUGINS.md`: New technical documentation covering the architecture and data flow. AI-generated/human-refined summary of the structure and architecture of the feature, to ease future maintenance. Platform updates: - Bumped IntelliJ Platform sinceBuild to 242 and updated JVM toolchain to 21 to match the new base IJPL version's. - Added `org.jetbrains.idea.maven` as a required plugin dependency, as it exposes the Maven machinery we use under the hood. - Refined dependency exclusions in `build.gradle.kts` to avoid runtime leaks and conflicts. Areas Touched: - Configuration: `DetektConfig`, `DetektPluginSettings`, `.idea/detekt .xml`. - Runtime: `ConfiguredService` (classpath management), `plugin.xml`. - UI: Main settings panel (`DetektConfigUi`) and a new `ui` package for Maven interaction. - Tests: Comprehensive suite covering GAV parsing, cycle detection, and resolution logic. AI Disclosure: This change was co-developed using LLM-based agents (primarily Gemini 3 models, and a bit of Claude 4.5 too). That said, all the code has been at least manually reviewed, and often tweaked or refactored too, by hand by the author.
819cfb7 to
99fed7f
Compare
Overview
This PR introduces a sophisticated system for managing detekt plugins directly from the IDE. Users can now extend detekt with third-party rule sets (such as those found on the detekt marketplace) via Maven repositories, complete with automatic transitive dependency resolution and a local lifecycle management system.
Demo:
demo.mp4
Downloaded plugin JARs:

Key Advantages
Architectural Highlights
PluginDependencyServiceto orchestrate the lifecycle of plugin JARs. Plugins are now stored in a project-local folder (.idea/detektPlugins/) and tracked via a state file,downloaded.json.JarRepositoryManagerandArtifactRepositoryManager), we can reliably discover and resolve detekt plugin artefacts through the newMavenDependencyResolverandMavenArtifactFetcher.DependencyExclusionEditorfor selective exclusion of transitive dependencies. It is a fork of IntelliJ’s own private UI for JPS, but with extra rules and code to support our specific needs.Further details are available in the
DETEKT_PLUGINS.mdfile, which is provided for guidance and future reference.Main parts
PluginDependencyServiceMavenSearchDialogDependencyExclusionEditorDETEKT_PLUGINS.mdPlatform Updates
sinceBuildto 242 (2024.2).org.jetbrains.idea.mavenas a required plugin dependency to expose underlying Maven machinery.Future Improvements
Note
While I have performed extensive manual testing and the PR includes a comprehensive suite of automated tests (covering GAV parsing, cycle detection, and resolution), please perform a thorough manual review and test cycle.
Maven infrastructure can be unpredictable across different environments/caches, and transitive dependency "fun" can manifest in unexpected ways.
Important
AI Disclosure: this change was co-developed using LLM-based agents (primarily Gemini 3 models, and a tiny bit of Claude 4.5 too). That said, all changes in this PR have then been manually reviewed, tweaked, and refactored by yours truly to minimise changes and ensure consistency.