The kotlin-netbeans plugin (JetBrains, abandoned in 2020) provides Kotlin support in NetBeans IDE.
The goal is to revive the project under a new name, clean up the infrastructure, migrate to the K2
compiler API, and bring language support to a level comparable to the IDEA plugin.
Key constraints:
- Existing packages (
org.jetbrains.kotlin.*) are not renamed; new and substantially reworked code goes intoio.github.nbplugins.kotlin.nbm.*. - Current state (0.11.x): K2-only architecture, Kotlin 2.3.21, platform era 253.
- Java 17 — runtime for tests.
Throughout all stages (A and B): when touching any module or dependency, update it to the latest compatible version. Not a separate stage — done along the way.
Guidelines:
- NetBeans Platform API (target cluster) — latest stable release
- Maven plugins (
nbm-maven-plugin,maven-compiler-plugin, etc.) — latest versions - Test dependencies (JUnit, etc.) — latest versions
kotlin-compiler: 1.9.25 (FE1.0 default) through B2–B6 (0.6.x). Bumps to 2.x in stage C after K2 migration completes.- IntelliJ platform: 193+241 mix in 0.5.x; core/core-impl/util bumps to 232 in B3 (0.6.x);
K2 migration in stage C adds
analysis-api-*-for-ideartefacts. - Java source/target: can be raised above 17 after B2.x if the ecosystem allows.
- A1 — Rename artifact and plugin metadata
- A2 — GitHub Actions CI/CD
- A3 — MIME type: switch to
text/x-kotlin, override built-in NB services - A4.1 — Maven multi-module: install
lib/*.jaras Maven artifacts (no compilation) - A4.2 — PATCHED JARs generated by Maven build (
PatchingJarsmodule); removed from git - A4.3 —
kotlin-formatter: compile from sources (submodules/Kotlin@v1.3.72); removelib/kotlin-formatter-1.0.jar - A4.4 —
kotlin-compiler: split into two JARs (compiler/compiler-intellij-platform); all bundled deps replaced by explicit Maven coords; removed ASM patches andkotlin-compiler-patched.pom - A4.5 — Eliminated strip-based ASM patches; replaced with Ant extraction (
<present>selector,<zipfileset exclude>); removed dead patch tools frompatches-src/ - A4.6 —
kotlin-converter: compile from sources; removePatchImportConversionKt,PatchFqnPart - A4.7 —
kotlin-ide-common: compile from sources; removePatchKotlinIdeCommon - A4.8 —
KotlinCompilerIntellijPlatform: replacePatchAstLoadingFilter,PatchExtensionsAddGetExtensionswith source classes inpatches/ - A4.9 —
openapi-formatter,idea-formatter: replaced withcode-style:241.194andcode-style-impl:241.194(JetBrains Maven); removedPatchContainerUtilAddMissing - A4.10 —
intellij-core: replaced withcore:193.7288.26+core-impl:193.7288.26(direct Maven deps of Nbm); removedIntellijCorewrapper,PatchingJars,patches-src/,lib/ - A4.11 — Eliminate
KotlinCompilerandKotlinCompilerIntellijPlatformsubmodules; usekotlin-compiler:1.3.72directly with exclusions; move patched classes (Extensions,ContainerUtilRt, message bundles) intoNbm - B1 — Research K2 Analysis API, choose architectural approach
- B2 — Bump
kotlin-compiler1.3.72 → 1.9.25 (FE1.0 preserved). See docs/plans/B2.0-bump-1.9.md. Ships as 0.6.x. - B3 — Bump IntelliJ
core/core-impl/util193 → 232 (code-stylestays 241); rebasePatchedCoreImplon 232 (not deleted — external 232 ≠ shaded 232 in kotlin-compiler). PR #36. - B4 — Replace
KotlinFormattersource module with binary artifactorg.jetbrains.kotlin:formatter:231-1.9.20-506-IJ8109.175; re-enable formatting/indentation tests. PR #37. - B5 — Replace
KotlinIdeCommonsource module with binary artifacts (base-fe10-analysis/code-insight/obsolete-compat/base-psi:231-1.9.20-506-IJ8109.175); re-enable intentions/quickfixes tests. 163 tests pass. - B6 — Repoint
KotlinConverter→submodules/IntellijCommunity@232(no binary artifact available for j2k); re-enable J2K/diagnostics tests - C — K2 Analysis API migration (C1–C10 complete). Ships as 0.7.x.
- D — Compiler upgrade to kotlin-compiler-ir-for-ide 2.3.21 + analysis-api 2.3.21, platform 253 (D1–D7 ✅). Ships as 0.8.x.
- E — Editor UX polish and missing features (E1–E12). Ships as 0.9.x+. (E1–E8 ✅, E8.5 ✅)
B3–B6 ship as 0.6.x on feature/kotlin-compiler-only; single PR after B6 passes all 169 tests.
Stage C ships as 0.7.x; C1–C10 complete.
Stage D ships as 0.8.x.
- Update
pom.xml - Create
src/main/nbm/manifest.mfwithOpenIDE-Module-Name layer.xml— no display-name changes neededBundle.properties— no changes needed (name set via manifest.mf)setup-local-repo.sh— no groupId/artifactId references to the main plugin
| Field | Before | After |
|---|---|---|
groupId |
Kotlin |
io.github.nbplugins |
artifactId |
kotlin.netbeans.plugin |
netbeans-plugin-kotlin-nbm |
version |
0.3.30-SNAPSHOT |
0.4.0-SNAPSHOT |
<name> in pom.xml |
Kotlin |
Netbeans Plugin Kotlin |
OpenIDE-Module (NB code-name) |
Kotlin.kotlin.netbeans.plugin |
io.github.nbplugins.kotlin |
OpenIDE-Module-Name (NB UI) |
Kotlin |
Kotlin Support |
Source packages are not renamed.
- Rename branch
master→main - Copy and adapt
.github/workflows/build.ymlfromNetbeansClaudeCodePlugin - Copy
build-scripts/autotag.sh - Research licenses (Apache-2.0 / JetBrains / IntelliJ Community) — whether Maven Central deployment is allowed (deferred)
- Configure publishing (Maven Central or GitHub Packages) (deferred)
Base on .github/workflows/build.yml and build-scripts/autotag.sh from NetbeansClaudeCodePlugin.
Adaptations:
- Main branch:
main - Replace all repository references with
io.github.nbkotlinplugin/netbeans-kotlin-plugin - Xvfb: remove explicit
xvfb-run— Xvfb is started automatically by pom.xml - Documentation: remove the pandoc step
Versioning scheme:
pom.xmlholdsMAJOR.MINOR.0-SNAPSHOT— only MAJOR.MINOR matters to CI- CI computes the version from git tags: base tag
MAJOR.MINOR+ commit count →MAJOR.MINOR.N
Release cycle:
- Starting a release: bump
pom.xmlto newMAJOR.MINOR.0-SNAPSHOT→ CI creates base tag - During development: add changes to
CHANGELOG.md(no version heading) - Finishing a release: add heading
# MAJOR.MINORor# MAJOR.MINOR (YYYY-MM-DD)toCHANGELOG.md→ CI sees the signal, creates tagMAJOR.MINOR.N, publishes GitHub Release, auto-replaces heading with# MAJOR.MINOR.N (date) - Patch releases on an old branch: branch
release/MAJOR.MINOR, same mechanism
CHANGELOG.md rules:
- Heading
# MAJOR.MINOR— only when finishing a release (CI signal) - During development — bullet lines at the very top of the file, no heading
- Each bullet starts with a past-tense verb:
Fixed,Added,Improved, etc. - Changes described from the user's perspective, not implementation
- Bullet committed together with the code change, never separately
Commit message rules:
- Start with a past-tense verb:
Fixed ...,Added ...,Improved ... - Subject describes what was done; body (if needed) — how and why
- When closing a GitHub issue: subject = CHANGELOG bullet text; body contains
Resolves: #N - Release-finish commit:
"Requested release MAJOR.MINOR"
Branch naming:
bugfix/<description>— bug fixesfeature/<description>— new featuresrelease/MAJOR.MINOR— patch branches for old versions- Backports:
bugfix/MAJOR.MINOR/<description>
- Study registration of
org.netbeans.modules.languages.kotlinin NB sources - Choose override mechanism
- Replace
text/x-ktwithtext/x-kotlinin all plugin registrations - Register our services with higher priority than the built-in ones
NetBeans 12+ includes basic .kt highlighting via org.netbeans.modules.languages.kotlin
(MIME type text/x-kotlin). Our plugin currently uses text/x-kt.
Goal: switch to text/x-kotlin with our services taking precedence over the built-in NB ones.
Override mechanism chosen after research: position in layer.xml, supersedes in
@ServiceProvider, or a module-level conflict declaration.
Phase 4.1 — Maven multi-module: copy existing JARs
- Create root
pom.xmlwithpackaging=pom - Create
bundled-jars/submodule with child modules for each JAR - Move the main plugin into
plugin/ - Package ASM patches as a
jar-patches/submodule - Delete
setup-local-repo.sh - Remove
lib/*.jarandlib/*.jar.bakfrom git
pom.xml (root, packaging=pom)
├── bundled-jars/
│ ├── pom.xml
│ ├── kotlin-ide-common/pom.xml — installs lib/kotlin-ide-common.jar
│ ├── kotlin-formatter/pom.xml — installs lib/kotlin-formatter.jar
│ ├── kotlin-converter/pom.xml — installs lib/kotlin-converter.jar
│ ├── intellij-core/pom.xml — installs lib/intellij-core.jar
│ └── ...
└── plugin/pom.xml — main plugin module (former root pom)
Phase 4.2 — PATCHED JARs generated by Maven build
- Create
PatchingJars/Maven module — compilespatches-src/*.java+ ASM into a fat JAR - Each bundled-jars module applies its patch chain via
exec-maven-plugin→ installstarget/patched.jar - Remove
lib/*-PATCHED.jarandlib/kotlin-compiler-1.3.72-PATCHED.pomfrom git - Move
lib/kotlin-compiler-1.3.72-PATCHED.pom→bundled-jars/KotlinCompiler/kotlin-compiler-patched.pom
| JAR | Phase 4.1 | Phase 4.2 |
|---|---|---|
kotlin-compiler-1.3.72 |
lib/ (PATCHED, in git) |
Maven Central → patched by build |
kotlin-formatter |
lib/ (PATCHED, in git) |
lib/ original → patched by build |
kotlin-ide-common |
lib/ (PATCHED, in git) |
lib/ original → patched by build |
kotlin-converter |
lib/ (PATCHED, in git) |
lib/ original → patched by build |
intellij-core |
lib/ (PATCHED, in git) |
lib/ original → patched by build |
openapi-formatter, idea-formatter |
lib/ |
lib/ (unchanged) |
Phase 4.3 — kotlin-formatter: compile from sources
- Add sparse git submodule
submodules/Kotlin(JetBrains/kotlin@v1.3.72), sparse-checkoutidea/formatter - Rewrite
bundled-jars/KotlinFormatter/pom.xml: packagingjar, compile withkotlin-maven-pluginfromsubmodules/Kotlin/idea/formatter/src/; fallback — extract embedded sources fromlib/kotlin-formatter-1.0.jar - Remove
lib/kotlin-formatter-1.0.jarfrom git - Remove
PatchFormatterBody.javafrompatches-src/(not needed when compiling from source)
Dependencies compiled against: netbeans-plugin-kotlin-openapi-formatter, idea-formatter,
intellij-core, netbeans-plugin-kotlin-compiler, org.jetbrains:annotations.
Phase 4.4 — kotlin-compiler: compile replacement classes from sources
- Reuse
submodules/Kotlin(already added in 4.3); sparse-checkout extended tocompiler/as needed - Compile replacement/patched classes from sources instead of ASM bytecode manipulation
- Remove remaining ASM patch steps for kotlin-compiler from
bundled-jars/KotlinCompiler/pom.xml - Remove no-longer-needed patch tools from
patches-src/
Phase 4.5 — Eliminate strip-based ASM patches
- Replace
PatchStripConflicts(intellij-core vs kotlin-compiler conflict resolution) with Ant<present>selector - Replace
PatchStripBundled(ConcurrentRefHashMap, plugin-owned classes, picocontainer, guava) with Ant<zipfileset exclude>and<delete> - Delete dead patch tools from
patches-src/:PatchStripConflicts,PatchStripBundled,PatchConcurrentRefHashMap,PatchConcurrentWeakHashMap,PatchExtensionsAddSetRootArea - Rename intermediate
patched.jar→${project.build.finalName}.jarin all bundled-jars modules
Phase 4.6 — kotlin-converter: compile from sources
- Add sparse-checkout for kotlin-converter sources in
submodules/Kotlin(j2k/, idea/idea-core/, idea/ide-common/, idea/idea-analysis/) - Rewrite
bundled-jars/KotlinConverter/pom.xml: compile from sources withkotlin-maven-plugin - Remove
lib/kotlin-converter-1.0.jarfrom git - Remove
PatchImportConversionKt.javaandPatchFqnPart.javafrompatches-src/
Phase 4.7 — kotlin-ide-common: compile from sources
- Add sparse-checkout for kotlin-ide-common sources in
submodules/Kotlin(idea/ide-common/) - Rewrite
bundled-jars/KotlinIdeCommon/pom.xml: compile from sources - Remove
PatchKotlinIdeCommon.javafrompatches-src/ - Remove
lib/kotlin-ide-common-1.0.jarfrom git - Add stubs in
Nbm/srcfor new abstract methods introduced by v1.3.72 API - Replace stubs with real implementations (
getResolutionFacadeByFile,getResolutionFacadeByModuleInfo,getResolutionFacade(platform),tryGetFrontendService,analyzeWithAllCompilerChecks)
Phase 4.8 — KotlinCompilerIntellijPlatform: replace stub patches with source classes
- Move
PatchAstLoadingFilterlogic to a source class inpatches/(stub that always returns) - Move
PatchExtensionsAddGetExtensionslogic to a source class inpatches/ - Remove
PatchAstLoadingFilter.javaandPatchExtensionsAddGetExtensions.javafrompatches-src/
Phase 4.9 — openapi-formatter, idea-formatter: compile from sources ✓ Done
- Add sparse-checkout for openapi/idea formatter sources in
submodules/IntellijCommunity - Rewrite
bundled-jars/OpenapiFormatter/andbundled-jars/IdeaFormatter/pom.xml: compile from sources - Remove
lib/openapi-formatter-1.0.jarandlib/idea-formatter-1.0.jarfrom git - Remove
PatchContainerUtilAddMissing.javafrompatches-src/
Phase 4.10 — intellij-core: replaced with Maven artifacts ✓ Done
- Add sparse-checkout for intellij-core sources in
submodules/IntellijCommunity - Replace
lib/intellij-core-1.0.jarwithcore:193.7288.26+core-impl:193.7288.26as direct Maven deps ofNbm - Remove
IntellijCorebundled-jars wrapper module - Delete
PatchingJars/module andpatches-src/directory entirely - Delete
lib/directory
Phase 4.11 — Eliminate KotlinCompiler and KotlinCompilerIntellijPlatform submodules
- Replace
netbeans-plugin-kotlin-compilerdep inNbmwith directkotlin-compiler:1.3.72dep, with<exclusions>for packages already provided by other deps (com/google,javaslang,org/picocontainer, etc.) - Move
patches/com/intellij/openapi/extensions/Extensions.java→Nbm/src/main/java/ - Move
patches/com/intellij/util/containers/ContainerUtilRt.java→Nbm/src/main/java/ - Move
patches/messages/JavaCoreBundle.propertiesandJavaErrorMessages.properties→Nbm/src/main/resources/messages/ - Remove
patches/com/intellij/util/AstLoadingFilter.javapatch (class already present incore:193.7288.26) - Delete
bundled-jars/KotlinCompiler/andbundled-jars/KotlinCompilerIntellijPlatform/modules - Remove both modules from root
pom.xmlreactor - Verify build and tests pass
Class conflict strategy: kotlin-compiler:1.3.72 embeds 3245 com/intellij/** classes; 1123 of
them duplicate core:193 + core-impl:193 + util:193 with different bytecodes. In the NBM
classloader the Nbm main JAR loads first, then ext/ JARs in dependency order. Since core:193
is declared before kotlin-compiler in Nbm/pom.xml, core:193 classes win. The remaining 1370
Java PSI classes (CoreJavaFileManager, PsiAnnotation, etc.) are unique to kotlin-compiler and
required at runtime — they are not available as separate Maven artifacts for the 193 era.
- Study the structure of
submodules/IntelliJCommunity/plugins/kotlin - Find a standalone mode for K2 (
analysis-api-standalone-for-ide) - Write an ADR with the chosen approach →
docs/adr/B1-k2-analysis-api-approach.md
Detailed plan: docs/plans/B2.0-bump-1.9.md
Ships as 0.6.x (branch feature/kotlin-compiler-only).
kotlin-compiler:1.9.25 ships a 232-era shaded com.intellij.* snapshot — aligned with
the external IntelliJ platform era we will pin in B3. FE1.0 (BindingContext, ClassDescriptor,
TopDownAnalyzerFacadeForJVM) stays intact throughout B2–B6; Nbm call sites are not rewritten.
A PatchedCoreImpl module was added to strip 193-era platform classes that conflicted with the
1.9.25 shaded snapshot — it is removed in B3 once the external platform aligns to 232.
Done in B2: kotlin.version 1.3.72 → 1.9.25; <languageVersion> 1.3 → 1.9; 49 tests
temporarily disabled (formatter/indentation/intentions fail due to binary incompat in bundled-jars
still compiled from submodules/Kotlin@v1.3.72); fixed in B4–B6.
- Bump
core,core-impl,utilfrom 193.7288.26 → 232.9921.47 in parentpom.xml code-style,code-style-implstay at 241.194PatchedCoreImplrebased from 193 → 232 (same strip-overlap approach; NOT deleted becausecore-impl:232.9921.47release and the 232-era snapshot shaded insidekotlin-compiler:1.9.25differ —CoreApplicationEnvironmentdiverged enough to break test init if the external JAR wins)- Added
VfsBundlestub (com.intellij.openapi.vfs) — removed fromcore:232, used byBuiltInsReferenceResolver bundled-jars/*still compile againstcore:193(unchanged until B4–B6)
Gate: 120/120 tests pass; no regressions.
Instead of repointing to IntellijCommunity 232 sources, used ready binary artifact
org.jetbrains.kotlin:formatter:231-1.9.20-506-IJ8109.175 from JetBrains Space Maven repo.
- Deleted
bundled-jars/KotlinFormatterentirely - Added JetBrains Space repo and
org.jetbrains.kotlin:formatterbinary dependency - Added runtime stubs bridging 241-era formatter API against kotlin-compiler:1.9.25 shaded classes:
DynamicBundle,FormatTextRanges,MultiMap,ObjectIntMap/ObjectIntHashMap,ObjectUtils(+reachabilityFence),misc/registry.properties - Removed
try/catch (NoSuchFieldError)fallbacks inKotlinIndentTask.ktandformatUtils.kt - Re-enabled 36 formatting/indentation tests
Gate: 154 tests pass.
Source compilation abandoned — 232-era base-fe10-analysis/src mixes K2 API classes
that can't compile without K2 Analysis API deps. Used 4 pre-built JARs from JetBrains Space
(packages.jetbrains.team/maven/p/ki/maven):
org.jetbrains.kotlin:base-fe10-analysis:231-1.9.20-506-IJ8109.175org.jetbrains.kotlin:base-fe10-code-insight:231-1.9.20-506-IJ8109.175org.jetbrains.kotlin:base-fe10-obsolete-compat:231-1.9.20-506-IJ8109.175org.jetbrains.kotlin:base-psi:231-1.9.20-506-IJ8109.175
Nbm source adaptations: ImportInsertHelper / KotlinCacheService / ResolutionFacade API changes
(231 era); @OptIn(FrontendInternals::class) on service methods; NotPropertyList.kt added (missing
from 231 JARs); jvmTarget bumped 11 → 17. Re-enabled 8 + 1 = 9 tests.
Gate: 163 tests pass.
- Source paths:
submodules/Kotlin/j2k/src→submodules/IntellijCommunity/plugins/kotlin/j2k/old/src(FE1.0 converter lives inold/; K2 converter is innew/) - Bump kotlin-maven-plugin in KotlinConverter to 1.9.25; drop
<languageVersion>1.3</languageVersion> - Re-validate two replacer-plugin patches (
emptyList(),runWriteAction) - Re-enable
J2KTest(5 methods) andDiagnosticsTest(1 method)
Gate: all 169 tests pass.
Starting point after B6: BindingContext (FE1.0), kotlin-compiler:1.9.25.
Target after C10: KaSession/KaSymbol (K2 Analysis API), kotlin-compiler:2.0.21.
Strategy:
- C1 ✓ done (PR #42) — Bump
kotlin-compiler1.9.25→2.0.21. Addanalysis-api-*-for-ide:2.0.21to classpath. Fix FE1.0 call sites for 2.0.21 API changes. Verify: all 169 tests pass, no analysis call-site changes yet.submodules/Kotlinstays at 1.9.25 (K2 Analysis API runtime is provided by the-for-ideJARs, not by the submodule sources). - C2 — Bump platform JARs and Kotlin submodule to 242/2.0.21-era:
submodules/Kotlin→v2.0.21(sparse checkout: only/*.md,/*.txt)- Bump binary platform JARs
core,core-impl,utilfrom232.9921.47/241.194to242.26775.26 - Bump
base-fe10-*from231-1.9.20-506-IJ8109.175to 242-era version - Add CoreImpl and KotlinCompiler reactor modules
KotlinConverter/pom.xmlandsubmodules/IntellijCommunityunchanged (stay at 232-era)- Verify: all tests pass, no analysis call-site changes yet.
- ✅ C3 — Set up
StandaloneAnalysisAPISessionalongside existingKotlinEnvironment(analysis-api-standalone-for-ide). Both analysis paths available simultaneously. - ✅ C4 — Migrate
resolve/,idea/util/—BindingContext→analyze { }/KaSession - ✅ C5 — Migrate
completion/— K2 primary path (KaCompletionProvider,KaCompletionProposalFactory); K1 fallback preserved. FixedcollectBinaryJarsto handlefile:-prefixed!/-suffixed classpath URLs from NetBeans Maven integration. - ✅ C6 — Migrate
highlighter/semanticanalyzer/— K2 primary path (KaSemanticHighlightingVisitor); K1 fallback preserved. AddedMultiMap(Map)constructor stub. FixedKtFunctionTypeparameter guard and splitanalyze {}blocks so deprecated-highlight failures don't discard symbol highlights. - ✅ C7 — Migrate
hints/,intentions/,fixes/— K2 primary path (KaImplementMembersFix, 7 K2 intentions,KaUnusedImportsComputer); K1 fallback preserved. Fixed hint-not-disappearing bug (wrapWithInvalidate for quick-fixes) and duplicate-member bug (declaredMemberScope filter). Registered DataObject save listener so hints reappear after Ctrl+Z + Ctrl+S. - ✅ C8 — Migrate
navigation/— K2 primary path (KaNavigationUtils:resolveToSourcePsi,renderDeclarationTooltip,getSmartCastDescription); K1 fallback preserved innavigate()andgetToolTip(). - ✅ C9 — Migrate
structurescanner/,filesystem/lightclasses/. Added code folding (+/− controls,KotlinFoldTypeProvider); K2 Navigator panel (KaStructureScanner);KaLightClassGenerator. PR #52. - ✅ C10 — Remove
KotlinEnvironmentand all remainingBindingContextfallback code; removeKotlinIdeCommonmodule (allbase-fe10-*deps eliminated with FE1.0 code). Added temporaryFirIncompatibleClassExpressionCheckerworkaround for KT-75035/KT-83463 (null source crash); portedKaRemoveEmptyClassBodyIntention,KaRemoveEmptyPrimaryConstructorIntention; fixed last-linecomputeSuggestionsskip bug.
Note on C3 ordering: submodules/IntellijCommunity intentionally stays at 232-era through C3–C10.
Both KotlinIdeCommon (compiles base/fe10/analysis/src) and KotlinConverter (compiles j2k/old/src)
build successfully against 242 platform JARs from 232-era sources — verified after C2.
ADR: docs/adr/B1-k2-analysis-api-approach.md.
Starting point after C10: K2 Analysis API, kotlin-compiler:2.0.21 shaded (193-era com.intellij.*),
platform core/core-impl/util at 242, code-style at 241.
Target (achieved): kotlin-compiler-ir-for-ide:2.3.21 unshaded, platform era 253,
analysis-api 2.3.21.
Each substage is a separate branch (refactor/dN-...) and PR targeting upstream/main.
- ✅ D1 (
refactor/d1-bump-kotlin-compile-version) — Decouplekotlin-maven-pluginfrom bundled runtime: addedkotlin.compile.version=2.2.21; pluginManagement uses it; bumpedkotlin.runtime.languageVersion1.9 → 2.2; upgradedgmavenplus-pluginto 4.2.0 + Groovy 4.0.32 (Java 25 support).languageVersionstays 2.2 until context-receivers → context-parameters migration. PR #56. - ✅ D2 (
refactor/d2-remove-submodules) — No publicj2k-newbinary artifact exists; removedKotlinConvertermodule from reactor andnetbeans-plugin-kotlin-converterdep from Nbm; stubbedJava2KotlinConverter(shows "not available" dialog); removedJ2KTest; configuredsubmodules/IntellijCommunityas sparse (root-only checkout). J2K will be reimplemented in E6. PR #57. - ✅ D3+D5 (
refactor/d3-d4-compiler-platform-253) — Replacekotlin-compiler:2.0.21(shaded) withkotlin-compiler-ir-for-ide:2.3.21(unshaded); bumpanalysis-api-*-for-ide2.0.21 → 2.3.21; removeFirIncompatibleClassExpressionCheckerworkaround (KT-75035 fixed in ≥ 2.1.20). NewKotlinCompilerCliBasemodule extracts all classes absent from-for-ideand platform JARs (set-difference from fatkotlin-compiler.jar);CoreImplrepacks platform 253 as before. Explicit new runtime deps:kotlinx-collections-immutable-jvm:0.3.7,caffeine:3.1.8.Registrystub updated to exposeCompanioninner class (analysis-api 2.3.21 requirement). - ✅ bugfix/jdk-invisible-in-k2-session — Register JDK home as a
KtSdkModuledependency inKotlinAnalysisAPISession; registerCodeInsightContextManagerStubservice; strip bundledfastutilfromKotlinCompilerCliBase(conflicts withintellij-deps-fastutilinutil:253); bumpintellij-deps-fastutil8.5.11-18 → 8.5.13-jb4. Fixes false type errors and broken semantic highlighting for code that uses JDK types. - ✅ D5 (
refactor/d5-remove-stubs) — Removed 17 dead compatibility stubs fromNbm/src/main/java/com/intellij/: shaded-1.9.25 stubs (DynamicBundle,FormatTextRanges,Extensions,ObjectUtils,DependantSpacingImpl, …) and 193-era platform bridges (ServiceManager,DataLoader,ObjectIntHashMap,MultiMap,ContainerUtilRt, …). Retained 16 stubs still needed: formatter runtime stubs (Formatter,CustomCodeStyleSettingsManager,CodeStyleSettingsService,ConcurrentCollectionFactory,ConcurrencyUtil), compile-only stubs (Configurable,IndentOptionsEditor,Editor,CodeStyleSettingsCustomizable), extension-point base classes (CodeStyleSettingsProvider,LanguageCodeStyleSettingsProvider),Registry/RegistryValue(analysis-api 2.3.21 Companion wrapper),CodeInsightContextManagerStub(K2 service), and plugin-specific providers. 145 tests pass. - ✅ D6 (
refactor/d6-formatter-from-sources, PR #65) — Replacedorg.jetbrains.kotlin:formatter:231-1.9.20-506-IJ8109.175withbundled-jars/KotlinFormatterbuilt fromsubmodules/IntellijCommunity/plugins/kotlin/formatter/minimal/src/(253-era sources). 9 UI-panel files excluded from compilation; deferred to E5. - ✅ D7 (
refactor/d7-platform-253, PR #66) — Bumped platform JARscore/core-impl/util/code-style/code-style-impl242/241 → 253. AddedRegistry,RegistryValue,ConcurrentCollectionFactory,ConcurrencyUtil,CodeInsightContextManagerstubs to satisfy analysis-api 2.3.21 and kotlin-compiler-ir-for-ide 2.3.21 requirements at runtime.
Priority order: E1 → E2 → E3 → E4 → E5 → E6 → E7 → E8 → E9 → E10 → E11 → E12
-
E1 — Editor UX polish (sub-items in priority order):
- K2 semantic highlighting live-update: fixed drift while typing unsaved changes (PR #71)
-
FUNCTION_CALL,EXTENSION_FUNCTION_CALL,SUSPEND_FUNCTION_CALL,CONSTRUCTOR_CALLsemantic tokens added toKotlinHighlightingAttributesandKaSemanticHighlightingVisitor - Fonts & Colors: 50+ named color categories matching IDEA exactly, organised in 10 groups;
3 theme XMLs in
highlighter/colors/:FlatLafLight.xml(IntelliJ Light),FlatLafDark.xml(Darcula),NetBeans55.xml(Classic NetBeans) (branchfeature/e2-idea-color-parity) - Fonts & Colors preview: semantic highlights applied to preview sample via
PreviewSemanticHighlightsLoader(branchfeature/e2-idea-color-parity) - Source / History toolbar buttons for
.ktfiles: registeredMultiViewElement(History view) alongside Source; removed empty Visual tab (PR #74) - Reformat selection: CSL Reformat action works on a selected range; Format context menu item added (PR #76)
- Auto-indent on paste:
KotlinIndentTaskhandles paste events, preserving relative indentation of pasted block (PR #77) - Completion filtering: dot-receiver completion uses receiver type's member scope; only members and applicable extensions are shown (no locals, outer-class members, or imported classes)
- Completion signatures: RHS shows
(param: Type): ReturnTypefor functions and: Typefor properties, rendered via K2KaTypeRendererForSourceinsideanalyze {} - Completion icons: Kotlin-accurate icons (val, var, method, extension function, suspend function, interface, enum, object, type alias, parameter) via
bundled-jars/KotlinIcons(SVG→PNG from IntelliJ Community sources at build time) - Completion deduplication and IDEA-like sort order: locals first, then type members (properties before methods), then package/import scope; duplicates (same name+signature) suppressed
- Hover tooltip: pausing the mouse over a Kotlin identifier shows a popup with a syntax-highlighted signature, container info, and KDoc sections; Ctrl+hover shows identical content; completion documentation popup shows each candidate's own docs (not always the first candidate's)
- False-positive
QUALIFIED_EXPRESSION_WITHOUT_SELECTOR— investigated; no longer reproduced with K2 2.3.21 -
ClassNotFoundException: org.codehaus.plexus.util.PropertyUtilsSEVERE on J2SE project open: replaced Maven Embedder utility withProperties.load()(PR #75).
-
E2 — Extended diagnostics and highlighting:
-
@Deprecatedsymbols: grey-strike rendering viaKaSymbol.deprecationStatus(added asKOTLIN_DEPRECATEDtoken in color parity work, branchfeature/e2-idea-color-parity) - Unused variables / unused parameters: K2
KaDiagnosticProviderchecks - Full K2 diagnostic set (exhaustive
when, type mismatch, unresolved reference) exposed in the NetBeans gutter + error stripe
-
-
E3 — Parameter info and inlay hints:
- Ctrl+P (ParameterInfo): CSL
ParameterInfoservice; function signature popup with active parameter highlighted (PR #86) - Inlay hints (parameter names at call sites): deferred — no public NetBeans 23 inlay-hints API found
- Ctrl+P (ParameterInfo): CSL
-
E4 — Extended intentions and quick-fixes matching IDEA set:
- 43 code intentions (Groups A–H): missing
whenbranches, if↔when conversions, string template↔concat↔buildString conversions, lambda↔reference↔anonymous function conversions, forEach↔for loop, named argument add/remove, brace add/remove, property accessor generation, De Morgan's law, type argument insert/remove, null-safety fixes, type mismatch fixes, modifier fixes, and more (PR #87) - 17 K2 quick-fixes from IDEA with infrastructure for standalone PSI mutation (PR #90)
- 43 code intentions (Groups A–H): missing
-
E5 — Formatter settings UI (PR #93):
KotlinCodeStyleSerializer/KotlinCodeStylePreferences— JDOM-based XML serialization (diff-from-defaults)KotlinCodeStylePreferencesProvider— NbPreferences bridge;ProjectCodeStyleStorage— per-project.kotlin-code-style.xml- Tools→Options→Kotlin:
KotlinOptionsPanelController+KotlinOptionsPanelwith IDEA-style layout: StyleBar (KotlinStyleBar+KotlinSchemeManagerwith Kotlin Official / Obsolete / IDE defaults profiles)- JSplitPane (6-tab panel | live preview via
KotlinFormattingPreviewPane)
- JSplitPane (6-tab panel | live preview via
- All 6 panels:
KotlinFormatterIndentPanel,KotlinFormatterSpacesPanel,KotlinFormatterCodeGenPanel(wrapping),KotlinFormatterBlankLinesPanel,KotlinFormatterImportsPanel,KotlinFormatterOtherPanel OptionTreePanel— reusable JTree with checkbox/combobox renderers- Per-project:
KotlinProjectOptionsPanelController+KotlinProjectCustomizerProvider
-
E6 — New Kotlin Class wizard (PR #TBD):
- Registered all 10 templates (Class, Interface, Data class, Enum, Annotation, Sealed class, Sealed interface, Abstract class, Object, File) in layer.xml; previously @TemplateRegistration annotations were silently ignored due to -proc:none
- Added KtDataClassWizardIterator, KtAnnotationWizardIterator, KtSealedClassWizardIterator, KtSealedInterfaceWizardIterator, KtAbstractClassWizardIterator
- FQN support (com.example.MyClass → package + short name) already present in TargetChooserPanelGUI
-
E7 — Find Usages (Alt+F7):
KaFindUsagesComputer— K2 core: resolves target PSI at cursor, iterates all project KtFiles, collectsOffsetRanges viasym.psi == targetPsicomparisonKotlinWhereUsedPlugin—RefactoringPluginwiring: extracts document/offset from lookup, calls computer, addsKotlinFindUsagesResultElemententries to bagKotlinWhereUsedRefactoringUI—RefactoringUIadapter: resolves symbol name for dialog title, no options panelKotlinActionsImplementationProvider— addedcanFindUsages/doFindUsagesKotlinRefactoringsFactory— addedWhereUsedQuerybranchlayer.xml— fixed silently-broken Rename refactoring (added Services/ entries for factory + provider, missing because-proc:nonesuppresses@ServiceProvider); addedWhereUsedAction.shadowto editor popup and file-node context menu (mirrors x-java registration that refactoring-api adds only for Java)
-
E8 — Navigate menu parity with Java:
- Go to Declaration (Ctrl+B) and Go to Source (Ctrl+Shift+B):
KotlinDeclarationFinderregistered viaKotlinLanguage.getDeclarationFinder(); wires into existingCslEditorKit/GoToDeclarationActionchain already in layer.xml - Go to Test/Tested class (Ctrl+Alt+T):
KotlinTestLocator(TestLocatorSPI, globalServiceProvider); convention-based Foo ↔ FooTest name matching - Go to Super Implementation (Ctrl+Shift+P):
KotlinGoToSuperTypeAction+KotlinOverridingMethods.overrides()(K2allOverriddenSymbols); registered as custom action with keybinding inKotlinKeyBindings.xml(CSL does not auto-provide this; Java-only injava.editor) - Go to Implementation (Ctrl+Alt+B):
KotlinGoToImplementationsAction+KotlinOverridingMethods.overriddenBy(); scans project KtFiles similarly to Find Usages - Inspect Members (Ctrl+Shift+F12):
KotlinShowMembersActionopens and focuses the Navigator window (popup-text "Inspect Members"); existingKaStructureScanneralready populates Navigator content - Editor right-click Navigate submenu (
Editors/text/x-kotlin/Popup/goto) registered to mirror Java's submenu: goto-source, goto-declaration, GotoOppositeAction shadow (Go to Test), goto-super-implementation, goto-implementation, separator, kotlin-inspect-members - Inspect Hierarchy (Alt+Shift+F12): deferred to E8.5 — needs
TypeHierarchyQuerySPI, separate from CSLDefaultLanguageConfig
- Go to Declaration (Ctrl+B) and Go to Source (Ctrl+Shift+B):
-
E8.5 — Inspect Hierarchy (Alt+Shift+F12): type hierarchy tree;
TypeHierarchyQuerySPI investigation required -
E9 — Refactoring rewrites via K2 Analysis API + IDEA source reuse
Strategy: compile IDEA K2 refactoring sources from
submodules/IntellijCommunity/plugins/kotlin/refactorings/kotlin.refactorings.k2/inside theKotlinRefactoringreactor module viamaven-resources-plugin(same pattern asKotlinFormatter/KotlinHighlighting), then add thin stubs for IDE-only types absent at runtime (WriteCommandAction,ApplicationManager,DataContext,OccurrencesChooser). NetBeansRefactoringPlugin/RefactoringUIadapters call into the compiled IDEA engine — no manual re-implementation of algorithms. E9.1 and E9.2 (Safe Delete) are the only hand-written exceptions (trivially built on K2analyze {}+ Find Usages).KotlinRefactoringreactor module — introduced in E9.3; jar module that compiles IDEA refactoring sources fromsubmodules/IntellijCommunitytogether with local stubs and compatibility shims. Follows the samemaven-resources-plugincopy pattern asKotlinFormatter/KotlinHighlighting. TheNbmmodule depends on this jar; both are part of the root reactor somvn packagefrom root is the correct build command (the NBM plugin resolves inter-module dependencies via the workspace reader within a single invocation; a separatemvn installstep is not needed).Runtime service injection pattern — IDEA's
codeInliner/engine calls services (PsiSearchHelper,ShortenReferencesFacility, …) viaservice<T>()/T.getInstance(). In standalone mode these are missing. The pattern used in E9.3 and applicable to all future E9.x refactorings:- Register a no-op or NB-aware implementation in
KotlinAnalysisAPISession.registerStandaloneServices()/installNoOpPsiSearchHelper()before the refactoring engine is first called. - Register missing extension points (e.g.
com.intellij.referencesSearch) inregisterHighlightInfoFilterEP(). - Document every added stub/service in docs/stubs.md.
Cursor-on-declaration-or-usage — every
Ka*Computermust resolve the target declaration from the caret regardless of whether the caret is on the declaration itself or on a reference to it. Standard approach (used in E9.3, required for E9.4+):- Find the leaf element at the caret:
ktFile.findElementAt(offset). - Walk up to a
KtNameReferenceExpression; if found, call K2analyze { ref.mainReference.resolveToSymbol()?.psi }— this gives the declaring element directly. - Only if step 2 yields nothing, fall back to
PsiTreeUtil.getParentOfType(element, KtXxx::class.java)to handle the case where the caret is on the declaration keyword or name token.
-
E9.1 — Rename (Alt+Shift+R): K2-based
KaRenameComputer(hand-written; PR #101) -
E9.2 — Safe Delete: K2-based
KaSafeDeleteComputer(hand-written; PR #102)- Hand-written: K2
analyze {}+KaFindUsagesComputer→ collect all usages →Problem(false, "Used in N places")if any; on confirm delete declaration - NetBeans adapter:
KotlinSafeDeletePlugin/KotlinSafeDeleteUIinNbm
- Hand-written: K2
-
E9.3 — Inline variable / property (Ctrl+Alt+N) — IDEA
codeInliner/engine port- IDEA sources (compiled into
KotlinRefactoringviamaven-resources-plugin):kotlin.refactorings.k2/inline/codeInliner/{CodeInliner, CodeToInlineBuilder, CallableUsageReplacementStrategy, PropertyUsageReplacementStrategy, InlinePostProcessor, InlinePreprocessorUtil, introduceValue}.kt;kotlin.refactorings.common/inline/codeInliner/{AbstractCodeInliner, AbstractCodeToInlineBuilder, AbstractInlinePostProcessor, AbstractPropertyUsageReplacementStrategy, CodeToInline, CommentHolder, InlineDataKeys, inlineUtils, MutableCodeToInline, ReplacementPerformer, UsageReplacementStrategy}.kt;kotlin.refactorings.common/inline/{AbstractKotlinInlinePropertyHandler, AbstractKotlinInlinePropertyProcessor, AbstractKotlinInlinePropertyDialog}.ktplus their abstract parents (AbstractKotlinInlineNamedDeclarationProcessor,AbstractKotlinDeclarationInlineProcessor,AbstractKotlinInlineDialog,KotlinInlineActionHandler). - Stubs/service registrations (see docs/stubs.md for details):
BaseRefactoringProcessor(JVM linkage stub inNbm/src/main/java/),UsageViewDescriptor(compile-only interface),NoOpPsiSearchHelper(project service, registered inKotlinAnalysisAPISession),KotlinSymbolBasedShortenReferencesFacility(application service wrapping IDEAinternalSymbolBasedShortenReferencesFacilityvia delegation, inKotlinRefactoring). - NetBeans adapter (in
Nbm):KotlinInlineVariablePlugin— NBRefactoringPlugin;KaInlineVariableComputerdrivesextractInitialization+createReplacementStrategyForProperty; per-usagestrategy.createReplacer(usage).invoke()loop insideNbDocument.runAtomicAsUser; followed byKotlinFormatterUtils.formatRangeon each inserted range. Flow control stays on NB side — IDEA'sBaseRefactoringProcessor.run()is intentionally not invoked.KotlinInlineVariableUI— NBRefactoringUI; preview pane lists usage ranges.KotlinInlineVariableRefactoring—AbstractRefactoringcarrying doc + offset.KotlinInlineVariableAction—BaseAction("kotlin-inline-variable"), Ctrl+Alt+N; registered inRefactormenu andEditors/text/x-kotlin/Actions/inlayer.xml.
- Caret or a selected identifier resolution works on declaration and any usage — see Cursor-on-declaration-or-usage in E9 strategy above.
- Supports local
valand a localvarwith its sole definition in the declaration initializer. A K2-backed standalone-source scan rejects assignments and increment/decrement writes before the IDEA engine is invoked and identifies the conflicting expression; receiver/member/accessor, Java, and index-only write coverage remain outside this adapter's scope.
- IDEA sources (compiled into
-
E9.4 — Inline function (Ctrl+Alt+N)
- IDEA sources:
inline/codeInliner/CodeInliner.kt,inline/codeInliner/CodeToInlineBuilder.kt,inline/codeInliner/CallableUsageReplacementStrategy.kt,inline/codeInliner/introduceValue.kt,inline/KotlinInlineFunctionProcessor.kt - Stubs:
WriteCommandAction,ApplicationManager - NetBeans adapter:
KaInlineFunctionComputer;KotlinInlineFunctionPlugin/KotlinInlineFunctionUI(option: this occurrence / all) inNbm
- IDEA sources:
-
E9.5 — Extract function (Ctrl+Alt+M)
- IDEA sources:
introduce/extractionEngine/ExtractionDataAnalyzer.kt,introduce/extractionEngine/Generator.kt,introduce/extractionEngine/KotlinTypeDescriptor.kt,introduce/extractionEngine/KotlinNameSuggester.kt,extractFunction/ExtractableCodeDescriptor.kt,extractFunction/ExtractionData.kt,extractFunction/ExtractionResult.kt,extractFunction/parametersUtil.kt,extractFunction/Parameter.kt - Stubs:
WriteCommandAction,ApplicationManager,ProgressManager - Risk:
computeExitPointSnapshot— verify availability inanalysis-api:2.3.21standalone; fallback: manual PSI visitor for return expressions - NetBeans adapter:
KaExtractFunctionComputer;KotlinExtractFunctionPlugin/KotlinExtractFunctionUI(name input + param table) inNbm
- IDEA sources:
-
E9.6 — Introduce variable (Ctrl+Alt+V)
- IDEA sources:
introduce/introduceVariable/K2IntroduceVariableHandler.kt,introduce/introduceVariable/KotlinIntroduceVariableServiceK2Impl.kt,introduce/introduceVariable/introduceVariableUtil.kt,introduce/K2SemanticMatcher.kt,introduce/K2ExtractableSubstringInfo.kt - Stubs:
OccurrencesChooser(→ replace all, or NB dialog);Editornot passed — computer operates headlessly - NetBeans adapter:
KaIntroduceVariableComputer;KotlinIntroduceVariablePlugin/KotlinIntroduceVariableUIinNbm
- IDEA sources:
-
E9.7 — Move Declaration (Refactor menu; no F6 keybinding to avoid a NetBeans conflict)
- IDEA sources ported (
kotlin.refactorings.move.k2/src/):descriptor/{K2MoveDescriptor, K2MoveSourceDescriptor, K2MoveTargetDescriptor, K2MoveOperationDescriptor}.kt,processor/{K2MoveDeclarationsRefactoringProcessor, moveUtil, moveUsageUtil, moveConflictUtil}.kt,processor/conflict/**(all 10 conflict checkers — visibility, name-clash, overridden-in-subclass, sealed-class-hierarchy, type-parameter-usage, implicit-package-prefix, module-dependency, internal-member-usage, actual/expect, plus helpers). Excluded (out of scope):K2MoveHandler.kt(IDE action dispatch),ui/**(Swing — NB has its own text-field UI),K2MoveFilesOrDirectoriesRefactoringProcessor.kt(file/dir moves; F4.1 now ports its Kotlin handler through a lifecycle-free adapter),K2ChangePackageDescriptor.kt/processor (separate F4.2 feature). - Single-module architecture: this plugin has no multi-module/multiplatform project model
anywhere (confirmed via dedicated research — every NetBeans project gets one isolated K2
analysis session).
SingletonModule/ModuleUtilCore/ModuleTypestubs (KotlinRefactoring/src/main/kotlin/com/intellij/openapi/module/) model this correctly rather than faking multi-module support; cross-module conflict checks (module-dependency/internal-member/actual-expect) always correctly report no conflict. - Real (non-stub)
KaModulebridge:org.jetbrains.kotlin.idea.base.projectStructure.kaModuleBridge.ktresolvesModule.toKaSourceModuleContainingElement/getKaModuleOfTypeSafeviaanalyze(element) { useSiteModule }instead of an IDE project-structure index lookup. - Hierarchy/inheritor search (
functionOverriddenInSubclassConflict,sealedClassesConflict) uses the standalone K2 build-session bridge:KotlinStandaloneInheritorSearchscans Kotlin source files for inheritors and override chains, and the compatibleOverridingDeclarations.forEachOverridingElement/KotlinSearchUsagesSupportAPIs expose those results to copied IDEA code. Java/library results and full IDEA-index conflict coverage remain unavailable. KotlinMoveUsageSearchService(new interface inKotlinRefactoring, real implKotlinMoveUsageSearchServiceImplregistered fromNbm'sKotlinAnalysisAPISession): whole-project external-usage search reusing the same file-iteration strategy as Find Usages (E7)'sKaFindUsagesComputer, sinceReferencesSearch/PsiSearchHelperis a no-op standalone. BacksfindMoveDeclarationUsages.kt, which reimplements the essential subset of the removed (patch #14, Copy Declaration/E9.19)K2MoveRenameUsageInfo.find().KaMoveDeclarationComputer.move()calls the real, unmodifiedK2MoveDeclarationsRefactoringProcessor.performRefactoring()— not a hand-rolled reimplementation. Getting there required identifying and fixing several genuine standalone-environment bugs (each a real fix, not a workaround, applied via the sameKotlinRefactoring/pom.xmlgroovy-patch mechanism used for every other era-compatibility issue in this module):- Read-only target directory: this environment's analysis-session
KtFiles are in-memoryLightVirtualFile-backed; anyPsiDirectory/VirtualFilereached via disk (VirtualFileManager/KotlinLocalFileSystem) is read-only for PSI mutation, soK2MoveTargetDescriptor.File's directory-based target resolution (getOrCreateTarget/getTarget, both routed throughPsiDirectory.findFile()) can never reach a writable file. Fixed withSessionAwareTargetDirectory(inKaMoveDeclarationComputer.kt) — aPsiDirectorydelegate that forwards every member IDEA's conflict-detection code reads (module, FqName, project, ...) to the real disk directory, but overridesfindFile()to return the already-writable targetKtFiledirectly (obtained the same way Copy Declaration/E9.19 does: write the file via NetBeansFileObject, refreshKotlinAnalysisAPISession, thengetKtFileForPath). LightVirtualFiledoesn't support file deletion: when the source file becomes effectively empty,performRefactoring()deletes it outright;LightVirtualFileBase's VFS doesn't implementdeleteFile(). Patched torunCatching { it.delete() }— the move itself already succeeded by this point, so the emptied (package-directive-only) file is left on disk instead of losing that result.com.intellij.refactoring.rename.RenameUtilnot on the standalone classpath: called byretargetUsagesAfterMovefor non-code usages, which are always empty here (findNonCodeUsagesis patched toemptyList(), noTextOccurrencesUtilstandalone) — the call was real dead code at runtime; patched away along with its import.addElementsToTarget()'soldToNewMaponly mapped nested declarations, never the moved top-level element itself (withChildDeclarations()excludes the receiver). Real IDEA gets away with this because itsMoveRenameUsageInfo.referencedElementre-resolves through a document-synced smart pointer that keeps following the element across the move; this plugin's simplifiedMoveRenameUsageInfostub (Nbm, no PSI-document sync) resolves it via a plainSmartPsiElementPointer, which doesn't. PatchedaddElementsToTarget()to also map the moved element itself — a real, general correctness fix for external-usage retargeting of any top-level declaration, not standalone-specific.- Retarget-before-delete reordering: for the same smart-pointer reason as #4, retargeting
usages after
deleteMovedElement()(IDEA's real order) findsreferencedElement == nullonce the original is deleted. PatchedperformRefactoring()to callretargetUsagesAfterMove()before deleting the source elements/files. - Import-directive references excluded from
KotlinMoveUsageSearchServiceImpl's search: retargeting a reference that's literally part of an existingimportstatement (as opposed to a code usage) left theKtImportDirectiveinvalidated mid-bindToElement(), standalone — no live-document sync to keep the import list consistent across aK2ReferenceMutateServicerestructure. Not needed anyway: retargeting the code usage (call site, etc.) to a fully-qualified reference and then shortening it already adds/removes the right import via Kotlin's own shorten-references pass, exactly as it does for Copy Declaration.
- Read-only target directory: this environment's analysis-session
- Retargeting an external (cross-file) usage is exercised for the first time by this
refactoring (Copy Declaration only ever retargets same-file/internal usages), and initially
hit a "requested stubbed spine during PSI operations"
LOG.error()call deep inK2ReferenceMutateService/PsiFileImpl— IntelliJ'sDefaultLogger.error()throws anAssertionErrorunconditionally unless a realLogger.Factoryis installed, which this standalone environment never did. Fixed environment-wide (not just for Move) by installingLenientLoggerFactory(Nbm/.../resolve/LenientLogger.kt) — ajava.util.logging-backedLoggerimplementation that logserror()instead of throwing — viaLogger.setFactory(...)at the top ofKotlinAnalysisAPISession.initApplicationEnvironment(), before any bundled IDEA class can callLogger.getInstance(). - NetBeans adapter:
KaMoveDeclarationComputer(KotlinRefactoring);KotlinMoveDeclarationAction(Refactor menu) /KotlinMoveDeclarationUI(target package + file name fields) /KotlinMoveDeclarationPlugin/KotlinMoveDeclarationRefactoring(Nbm) - Source and target mutation is now staged through
KotlinRefactoringTransaction: a new target is removed on any conflict/error, an existing target is restored exactly, and Refactor → Undo Last Refactoring restores both documents (or removes the target file if the refactoring created it).
- IDEA sources ported (
-
F4.1 — Move Kotlin File and Directory (Refactor menu / folder context menu)
- Ports the Kotlin-specific
K2MoveFilesHandlerportion ofK2MoveFilesOrDirectoriesRefactoringProcessor.ktthroughKaMoveFileComputer. The generic IDEA processor is intentionally not invoked: it depends on writable IntelliJ VFS, indexed generic-file search, command/listener lifecycle, and modal UI unavailable in standalone K2. - Refactor → Move Kotlin File... selects a destination source root and package. NetBeans owns
physical movement through
KotlinRefactoringTransaction; the K2 adapter updates a package only where source-root-relative package/directory alignment proves it safe, checks portable Kotlin conflicts, and retargets supported Kotlin references. - Transactions now record reversible physical file moves and transaction-owned destination folders; failed writes roll back the path and document snapshots, while Undo Last Refactoring restores the original path and text.
- Folder-node Move Kotlin Directory... recursively moves only Kotlin descendants through one atomic transaction, retaining the selected directory and every nested Kotlin folder below the target package; a single K2 pass uses per-file target packages so inter-file references remain coherent. Non-Kotlin descendants remain at their source paths.
- Portable coverage includes matching-package update, package/directory mismatch preservation, K2 semantic adapter execution, physical-move rollback, owned-folder cleanup, and undo. The remaining F4.1 scope is generic non-Kotlin content, Java/comment/text/index-only references, and full IDEA project-model conflict behavior.
- Ports the Kotlin-specific
-
F4.2 — Change Kotlin Package (Refactor menu / folder context menu)
- Ports real upstream
K2ChangePackageDescriptorandK2ChangePackageRefactoringProcessorsources fromkotlin.refactorings.move.k2. The copied processor is patched only to remove IDEA'sBaseRefactoringProcessorcommand/progress/dialog/ listener lifecycle; its K2 usage discovery, conflict collection, package-directive rewrite, declaration mapping, and retargeting sequence remain the semantic engine. - Refactor → Change Kotlin Package... changes the active Kotlin file's package without moving it. A folder-node invocation recursively changes only Kotlin descendants; direct children use the entered package while nested descendants append their relative folder paths. The selected folder's name is not added because its physical path remains unchanged.
- Supported Kotlin code references and direct non-aliased imports update atomically through
KotlinRefactoringTransaction; Undo Last Refactoring restores every source and usage document. Java/comment/text/index-only references, full IDEA project-model conflicts, and arbitrary multi-selection remain outside the standalone scope.
- Ports real upstream
-
F4.3 — Move Nested Kotlin Member (Refactor menu)
- Adds Refactor → Move Nested Member... for the portable K2-native subset: a nested named class/object can move to a selected named class/object; a companion-object function/property can move only to a selected target declaring exactly one companion object.
KaMoveNestedMemberComputerretains IDEA K2 internal-reference marking, rebinding, and shortening support while the passive NetBeans target chooser receives controller-computed candidates and never invokes K2 directly.KotlinMoveNestedMemberPluginvalidates a freshly resolved source/target immediately before mutation, stages every returned changed file throughKotlinRefactoringTransaction, rolls back on a persistence failure, and supports Refactor → Undo Last Refactoring for source and target.- The intentionally narrow standalone boundary rejects instance members, constructors, enum entries, initializers, alias imports, duplicate targets, Java/non-code/comment/index-only scenarios, and external qualified usages whose rewrite has not been validated.
-
F7 — Rename Kotlin File and Package Directory (Refactor menu / folder context menu)
- Adds an explicit Refactor → Rename Kotlin File... command for the active
.ktfile. It usesKotlinRefactoringTransactionto rename only the physical basename and supports Undo Last Refactoring; package declarations and Java file-facade references are deliberately unchanged. The generic file Rename additionally renames a matching top-level Kotlin class and its supported Kotlin references through K2 before renaming the file. - Adds folder-node Rename Kotlin Package Directory..., which renames only the physical directory and its descendants while leaving package directives and references unchanged.
- The generic folder Rename (available for package folders below a conventional source root,
not for
src/main/kotlin/src/test/kotlinthemselves) renames the directory together with its Kotlin packages. Every descendant receives the package derived from its post-rename path (including files whose directive did not match the directory), andKaChangePackageComputerretargets supported Kotlin imports and references. Reference retargeting works on the captured source text: in standalone mode rewriting a package directive invalidates every PSI smart pointer held by K2UsageInfo, so imports and fully qualified references are rewritten by FQN token and callers that lose an implicit same-package binding receive an explicit import. The semantic pass runs on the original paths first, stages minimal hunk texts throughKotlinRefactoringTransaction, and lets the single commit write those documents before renaming the folder, so conflicts are reported before any physical change and Undo Last Refactoring restores paths, texts, and open-editor carets together. Change Kotlin Package... remains the package-only operation. - The generic IDEA rename UI/lifecycle remains intentionally unported because it depends on writable IntelliJ VFS, indexed Java/file-facade search, automatic-renamer extensions, and action/command infrastructure unavailable in standalone NetBeans. Unicode/quoted names, Java/comment/text/index-only references, automatic renamers, and full project-model behavior remain outside this portable adapter.
- Adds an explicit Refactor → Rename Kotlin File... command for the active
-
E9.8 — Change Signature (Ctrl+F6) — PRs #114, #115
- IDEA sources:
changeSignature/KotlinChangeSignatureUsageSearcher.kt,changeSignature/KotlinChangeInfo.kt,changeSignature/KotlinChangeInfoBase.kt,changeSignature/KotlinParameterInfo.kt,changeSignature/KotlinMethodDescriptor.kt,changeSignature/KotlinChangeSignatureConflictSearcher.kt, all 11changeSignature/usages/Kotlin*Usage.ktclasses (function calls, parameter refs, overrides, callable references, constructor delegation, callers, data-class components/destructuring, enum entries, by-convention calls) - All 11 usage types covered: call sites (including through an overriding declaration and
by-convention operator calls,
box["key"]), in-body parameter references, overrides (project-wide), callable references (::foo),this(...)/super(...)constructor delegation, propagate-to-callers, data-class destructuring (val (a, b) = point, reordered to preserve each variable's binding), enum entries without a super call, and conflict detection (duplicate parameter names rejected) - Parameter reordering in the dialog (toolbar buttons + drag-and-drop); real
Refactor → Undo Last Refactoringsupport throughKotlinRefactoringTransaction, which commits every touched document or restores all of them after a write failure; a multi-hunk diff (TextRangeDiff) reformats only the actually-changed regions per file, not the whole file - Fixed a standalone-environment gap:
shortenReferences()throws for any constructor after a structural parameter-list change (K2 can't resolve the constructor's FIR node post-replace, since this plugin'sNoOpPomModelnever fires a real out-of-block- modification notification) — both call sites now fall back to fully-qualified type names instead of aborting the refactoring - Fixed a K2 reference-resolution gap: a data-class destructuring entry's reference
(
KaFirDestructuringDeclarationReference) doesn't resolve throughresolveToSymbol()at all — only throughmultiResolve(), which returns both the entry's own declaration and the constructor parameter it destructures - NetBeans adapter:
KaChangeSignatureComputer(KotlinRefactoring);KotlinChangeSignaturePlugin/KotlinChangeSignatureUI(param table with reorder buttons + drag-and-drop) /KotlinChangeSignatureUsageSearchServiceImpl(whole-project usage scan backing the ported engine'sReferencesSearchcalls) /TextRangeDiffinNbm
- IDEA sources:
-
E9.6+ — Enhanced Introduce Variable dialog:
KotlinIntroduceVariableUIadds "Replace all occurrences" checkbox (default on),val/varradio, "Specify type explicitly" checkbox; carried onKotlinIntroduceVariableRefactoring(replaceAll,useVar,explicitType) and applied byKotlinIntroduceVariablePlugin.performChange() -
E9.9 — Introduce Constant (Ctrl+Alt+C) — PR #108
- IDEA source:
introduceConstant/KotlinIntroduceConstantHandler.kt - Reuses most of
KaIntroduceVariableComputer; only compile-time constant expressions (literals, arithmetic on literals) accepted, validated via K2evaluate() - Inserts into companion object or top-level depending on context
- Files:
KaIntroduceConstantComputer,KotlinIntroduceConstant{Refactoring,Plugin,UI,Action}
- IDEA source:
-
E9.10 — Introduce Import Alias — PR #108
- IDEA source:
introduceImportAlias/KotlinIntroduceImportAliasHandler.kt - Target is a type reference inside an import statement:
import pkg.Class→import pkg.Class as Alias, all FQN usages replaced with the alias - No IDEA keybinding (Refactor menu / Alt+Enter on import only)
- Files:
KaIntroduceImportAliasComputer,KotlinIntroduceImportAlias{Refactoring,Plugin,UI,Action}
- IDEA source:
-
E9.11 — Introduce Property (Ctrl+Alt+F) — PR #109
- IDEA source:
introduceProperty/KotlinIntroducePropertyHandler.kt - Target: expression → class property (not local val); destination combo (primary constructor param / class body / companion object), initializer vs getter, replace-all-occurrences checkbox
- Files:
KaIntroducePropertyComputer,KotlinIntroduceProperty{Refactoring,Plugin,UI,Action}
- IDEA source:
-
E9.12 — Introduce Type Alias (Ctrl+Alt+Shift+A) — PR #109
- IDEA source:
introduceTypeAlias/KotlinIntroduceTypeAliasHandler.kt - Target: type reference (not expression) →
typealias Name = Type; visibility combo, replace-all-occurrences, and K2-backed same-file generic extraction with nested/qualified type-argument substitutions; star projections, local type parameters, class-body targets, expressions, and project-wide duplicate search remain unsupported - Files:
KaIntroduceTypeAliasComputer,KotlinIntroduceTypeAlias{Refactoring,Plugin,UI,Action}
- IDEA source:
-
E9.19 — Copy Declaration (F5) — PR #109
- IDEA source:
copy/CopyKotlinDeclarationsHandler.kt - Duplicates a declaration into a target file without removing it from the source (simpler than Move — no source-side import/reference updates)
- Files:
KaCopyDeclarationComputer,KotlinCopyDeclaration{Refactoring,Plugin,UI}; hooks into NB's built-in Copy action (F5), no newActionclass needed - The dialog selects a target source root, existing/new package, and target filename. Target
creation/replacement is staged through
KotlinRefactoringTransaction: failed copies roll back the target, and Refactor → Undo Last Refactoring removes a newly-created target or restores a pre-existing target's exact original text. Whole-file copies update the selected package and use IDEA's internal-usage retargeting pass before persistence.
- IDEA source:
-
E9.13 — Introduce Parameter (Ctrl+Alt+P) — PR #119
- IDEA source ported verbatim:
introduceParameter/IntroduceParameterDescriptor.kt(kotlin.refactorings.common) — itsvalVar/parametersToRemove/newArgumentValuelogic is driven as-is, not reimplemented KotlinFirIntroduceParameterHandler.kt(IDE action-system entry point, Editor/dialog/ inplace-introducer) is not ported;KaIntroduceParameterComputerhand-writes the caret/selection resolution and the mutation orchestration instead, reusing E9.8's portedKotlinMethodDescriptor/KotlinChangeInfo/KotlinParameterInfo/KotlinChangeSignatureUsageProcessorthe same wayKaChangeSignatureComputeralready does standalone- Target: expression inside a function/secondary-constructor body (or a class body/property
initializer, targeting its primary constructor) → new parameter; every existing call site
updated to pass the original expression explicitly; body occurrences (one or all, matched
via
K2SemanticMatcher) replaced by a reference to the new parameter - Dialog: name, type (editable combo pre-filled with the inferred type + supertypes), "replace all N occurrences" checkbox, "use default value" checkbox, target-scope combo when multiple enclosing declarations are available
- Known simplifications vs. real IDEA (documented in
KaIntroduceParameterComputer's class doc): a selection resolving to a localKtPropertyis rejected asNotApplicable; a lambda-argument occurrence is always replaced positionally (no named-argument heuristic); context parameters are not tracked by the internal-usage scan (out of scope — this plugin's language version is capped below context parameters, see Key Versions); aKtClasstarget with no primary constructor yet is out of scope (no "add one from scratch" path) - NetBeans adapter:
KaIntroduceParameterComputer(KotlinRefactoring);KotlinIntroduceParameter{Refactoring,Plugin,UI,Action}(Nbm). Every changed declaration and caller is staged throughKotlinRefactoringTransaction, retaining hunk-only formatting while rolling every file back if any persistence step fails.
- IDEA source ported verbatim:
-
E9.14 — Introduce Functional Parameter (Ctrl+Alt+Shift+P)
- Not a flag on E9.13's computer (that description didn't match real IDEA): real IDEA's
KotlinFirIntroduceLambdaParameterHandlerruns the Extract Function engine (ExtractionDataAnalyzer/Generator.generateDeclarationwithExtractionTarget.FAKE_LAMBDALIKE_FUNCTION) to compute which local variables/receiver the selection captures (these become the lambda's parameters), then drives the sameIntroduceParameterDescriptor/KotlinChangeSignatureUsageProcessorpipeline E9.13 already uses. New fileKaIntroduceFunctionalParameterComputer(KotlinRefactoring); usestargetParentitself (not an inner block) asExtractionData.targetSibling— ported verbatim fromKotlinFirIntroduceLambdaParameterHandler.invoke()— since the extracted code becomes a lambda literal living at each call site, not a nested local function, sotargetParent's own parameters must be captured explicitly rather than closed over - Un-stubbed
ExtractableCodeDescriptor.duplicates(KotlinRefactoring/pom.xmlpatch #13, previouslyemptyList()since E9.5/E9.6) to the realfindDuplicates(): it was pure analysis code, stubbed only because it transitively pulled in a few genuinely IDE-heavy functions (highlight/preview/processDuplicates*, needEditor) sharing a file (duplicateUtil.kt) with two pure ones (processWeakMatch/getControlFlowIfMatched) that are needed — the file is now included with the IDE-heavy half stripped by patch #13. Verified no regression to E9.5/E9.6/E9.11 via a newKaExtractFunctionTestfixture (withDuplicate) exercising a previously-impossible duplicate-occurrence path; the one real behavior change (anchor-selection now considers duplicate locations, matching real IDEA) is non-corrupting sincecomputeMinimalDiff'sformatEndOffsetalready covers the shifted region for the existing post-edit reformat pass - Known simplifications vs. real IDEA (documented in the class doc): single-expression
selection only (not a multi-statement block); an existing lambda-argument occurrence is not
given IDEA's double-lambda wrap; the final parameter's type text in the signature may appear
fully qualified (
kotlin.IntvsInt) — a pre-existing characteristic of the shared E9.8KotlinChangeSignatureUsageProcessorpipeline, not new to this feature; call-site lambda arguments are inserted positionally, not as an idiomatic trailing lambda - NetBeans adapter:
KaIntroduceFunctionalParameterComputer(KotlinRefactoring);KotlinIntroduceFunctionalParameter{Refactoring,Plugin,UI,Action}(Nbm). Its declaration and caller writes use the same hunk-preserving transaction and all-or-rollback failure contract as Change Signature and Introduce Parameter. - layer.xml position 1175
- Not a flag on E9.13's computer (that description didn't match real IDEA): real IDEA's
-
E9.15 — Extract Interface — PR #121
- IDEA source:
extractClass/K2ExtractSuperRefactoring.kt. - Creates a new
interfacefrom selected members, adds: Interfaceto the class. - NetBeans dialog selects the interface name, members, source root, package, and target Kotlin file;
source and target are committed through
KotlinRefactoringTransaction, so failed writes roll both back and Undo Last Refactoring restores an existing target or removes a generated one.
- IDEA source:
-
E9.16 — Extract Superclass — PR #121
- Reuses the E9.15
K2ExtractSuperRefactoringengine to create anabstract class. - Dialog additionally supports making selected members abstract and uses the same transactional source/target persistence and undo behavior as Extract Interface.
- Reuses the E9.15
-
E9.17 — Pull Members Up (Ctrl+Alt+U)
- Reuses the copied IDEA K2
PullUpProcessorand registeredK2PullUpHelperFactoryto move selected Kotlin declarations from a child class into a selected direct Kotlin superclass or interface. - Dialog supports cross-file targets, member selection, and a Make Abstract option; Preview Conflicts reports target-member collisions before NetBeans schedules a mutation.
- The NetBeans apply element snapshots, formats, and restores both source documents for Undo Last Refactoring.
- Current standalone conflict preview covers direct target-member collisions; IDEA's index-backed inheritor, visibility, and accidental-override checks remain unavailable until their project-search infrastructure is ported.
- Reuses the copied IDEA K2
-
E9.18 — Push Members Down (Ctrl+Alt+O)
- Reuses the copied IDEA K2 Push Down processor to move selected declarations from a superclass or interface into every direct Kotlin subclass in the related build scope.
- Dialog supports member selection and a per-member Make Abstract option; the NetBeans apply element snapshots, formats, and restores every changed source/child document for Undo Last Refactoring.
- Direct inheritors are discovered from writable K2 source files in the standalone session; project-index-only IDEA searches remain bridged by the standalone compatibility layer.
Common file-layout template for every E9.x refactoring:
KotlinRefactoring/src/main/kotlin/.../Ka*Computer.kt — headless K2 analysis, sealed Outcome KotlinRefactoring/target/generated-sources/refactoring/ — IDEA sources, copied via pom.xml Nbm/src/main/kotlin/.../refactoring/Kotlin*Plugin.kt — RefactoringPlugin (prepare → bag) Nbm/src/main/kotlin/.../refactoring/Kotlin*Refactoring.kt — AbstractRefactoring carrier Nbm/src/main/java/.../refactoring/Kotlin*UI.java — CustomRefactoringPanel + RefactoringUI Nbm/src/main/kotlin/.../refactoring/Kotlin*Action.kt — BaseAction, opens the dialog layer.xml — Actions, Menu (position), keybindingsReusable IDEA infrastructure already vendored in
generated-sources(no changes needed):K2SemanticMatcher(semantic-duplicate search),KotlinNameSuggester(name generation from type/context),K2ExtractableSubstringInfo(substring extraction),ExtractionData/ExtractionDataAnalyzer/Generator(Extract Function/Property).Target
Refactormenu layout (layer.xml position,[x]= wired today):Rename Shift+F6 ~100 [x] E9.1 Change Signature Ctrl+F6 150 [x] E9.8 Move F6 ~200 [x] E9.7 Copy F5 ~250 [x] E9.19 Safely Delete Alt+Delete ~500 [x] E9.2 --- separator --- 600 Extract Function Ctrl+Alt+M 700 [x] E9.5 Extract Interface 750 [x] E9.15 Extract Superclass 760 [x] E9.16 --- separator --- 900 Introduce Variable Ctrl+Alt+V 1000 [x] E9.6 Introduce Constant Ctrl+Alt+C 1050 [x] E9.9 Introduce Import Alias 1075 [x] E9.10 Introduce Property Ctrl+Alt+F 1100 [x] E9.11 Introduce Type Alias Ctrl+Alt+Shift+A 1125 [x] E9.12 Introduce Parameter Ctrl+Alt+P 1150 [x] E9.13 Introduce Functional Param Ctrl+Alt+Shift+P 1175 [x] E9.14 --- separator --- 1300 Inline Ctrl+Alt+N 1400 [x] E9.3/E9.4 Pull Members Up Ctrl+Alt+U 1450 [x] E9.17 Push Members Down Ctrl+Alt+O 1500 [x] E9.18 --- separator --- 1550 Undo Last Refactoring 1600 [x] (Change Signature, Move Declaration, Extract, Introduce, Inline, Pull Up, and Push Down) Redo Last Refactoring 1700Verification checklist for every E9.x refactoring:
mvn package -DskipTests— builds everythingmvn test -pl Nbm -Dtest=Ka<Feature>Test— unit tests- Manual test in NetBeans: open file → invoke refactoring → check dialog → preview → apply → undo
- CHANGELOG bullet updated together with the code
E9 is complete.
-
F5.1 — Inline Type Alias (Ctrl+Alt+N)
- Reuses IDEA K2's
TypeAliasUsageReplacementStrategyand compiledKotlinInlineTypeAliasProcessor; NetBeans deliberately owns the dialog, preview, transaction, and undo instead of invoking IDEA's processor lifecycle. - The unified Inline action resolves a type-alias declaration or usage; its NetBeans panel supports
all occurrences, the invocation occurrence only, and retaining the declaration. K2-generated
type substitutions/import changes are committed through
KotlinRefactoringTransactionso Undo Last Refactoring restores every touched Kotlin document. - Portable standalone scope is Kotlin source files registered in the active session; Java, non-code, and project-index-only references remain unavailable.
- Reuses IDEA K2's
-
F5.2 — Inline Anonymous Function / Lambda (Ctrl+Alt+N)
- Reuses IDEA K2's
KotlinInlineAnonymousFunctionProcessorfor immediate-call recognition,LambdaToAnonymousFunctionUtilfor K2-derived lambda signatures, andCodeInlinerfor the final substitution. NetBeans owns the UI, preview, transaction, and undo. - Standalone K2 needs a fresh session after IDEA converts a lambda to an anonymous
fun: the new PSI otherwise has no FIR mapping. The adapter commits only the final text throughKotlinRefactoringTransaction, so no intermediate source is persisted and Undo Last Refactoring restores the original document. - Supports immediately invoked Kotlin lambdas and anonymous functions. Non-invoked functions, Java/non-code/index-only references, and wider IDEA invocation/project-index cases remain unavailable.
- Reuses IDEA K2's
-
F8 — Structural conversions (operator/function conversions)
- Compiles the six IDEA K2 sources for the operator/function conversions into the new
KotlinCodeInsightImplreactor module:ReplaceCallWithBinaryOperatorInspection,ReplaceGetOrSetInspection,ReplaceContainsInspection(inspections-k2),ReplaceInvokeIntention,ReplaceCallWithUnaryOperatorIntention(intentions-k2), andRemoveEmptyParenthesesFromLambdaCallInspection(inspections-shared). The sources are copied fromsubmodules/IntellijCommunitybymaven-resources-pluginand compiled unchanged; the only patch is widening the threeinternal classinspections so the NetBeans layer can construct them. KotlinFixesImplwas extended with the remainingcode-insight/apiapplicable framework (KotlinApplicableInspectionBase,KotlinModCommandQuickFix,KotlinApplicableModCommandAction,ApplicabilityRange,ApplicableRangesProvider,ContextProvider) so those sources have something to compile against.KaIdeaIntentionHintandKaIdeaInspectionHintdrive the compiled actions by reflection (theirgetElementContext/createQuickFix/invoke/applyFixareprotected), reusingKaModCommandFix'sNoOpModPsiUpdaterand PSI→document sync.KaStructuralConversionHintsattaches each action to the PSI element the caret refers to, andKotlinHintsProvider.listOfK2Intentionsregisters them alongside the hand-written hints.- Covers
a.plus(b)→a + b,a.get(i)/a.set(i, v)→a[i]/a[i] = v,a.contains(b)→b in a,a.invoke(b)→a(b),a.not()/a.unaryPlus()→!a/+a, andf() {}→f {}. The reverse directions (KaOperatorToFunctionIntention,KaConvertLambdaToReferenceIntention) stay hand-written: their IDEA counterparts drag in a much larger slice ofcode-insight.
- Compiles the six IDEA K2 sources for the operator/function conversions into the new
- Register a no-op or NB-aware implementation in
-
E10 — J2K (Java→Kotlin) conversion
- Compiles IDEA's real J2K sources (
j2k/shared/src+j2k/k2/src) into the newKotlinJ2Kreactor module with standalone stubs, the same pattern asKotlinRefactoring/KotlinFixesImpl. The K2 post-processing subset fromcode-insight/fixes-k2was ported intoKotlinFixesImpl. - Entry point: Refactor → Convert to Kotlin on a Java file. The confirmation dialog runs
before anything is touched; the conversion then runs on a background thread as a headless
NetBeans refactoring (
JavaToKotlinRefactoring+JavaToKotlinPlugin+JavaToKotlinElement), so the sibling.ktcreation, its content, and the.javaremoval are one transaction registered in Undo Last Refactoring. The.ktappears only after the conversion succeeds; a failure rolls everything back and leaves the Java file intact. - Conversion itself:
NewJavaToKotlinConverterover the analysis session, K2 post-processing, and a final text-based formatting pass. - Standalone wiring in
KotlinAnalysisAPISession:StandaloneKaModuleProvider(replaces the index-based IDE provider), theorg.jetbrains.kotlin.j2kConverterExtensionextension point withK2J2KConverterExtension, and thecom.intellij.deepestSuperMethodsSearchextension point with a PSI-only executor — without them the engine throws "Missing extension point" on method symbols. J2KTestis re-enabled asJava2KotlinConverterTestover the existing fixtures, now with K2 output (for exampleSystem.out.printlnshortens toprintln).- Unsupported: Java copy/paste conversion, IDEA's project-configuration prompts, unused-import detection during conversion, and editor-level Ctrl+Z of the conversion (use Undo Last Refactoring instead).
- Compiles IDEA's real J2K sources (
-
E11 — New Project with Kotlin group:
ProjectWizardPanelintegration- Variants: Kotlin/JVM application, Kotlin/JVM library, Kotlin Script
-
E12 — Debugger: rewrite via reflection to bypass Friend-module restrictions (lowest priority)
- A1: stays
0.3.x, new Maven coordinates - A4 series:
0.4.x→0.5.x(cleanup of bundled JARs) - B2–B6 (Kotlin 1.9.25 + IntelliJ 232 bump, FE1.0 preserved):
0.6.x - C1–C10 (K2 Analysis API migration, kotlin-compiler 2.0.21):
0.7.x✓ - D1–D7 (kotlin-compiler-ir-for-ide 2.3.21, analysis-api 2.3.21, platform 253):
0.8.x✓ - E1–E5 ✓ (hover, diagnostics, parameter info, intentions/quick-fixes, formatter settings UI):
0.9.x→0.10.x→0.11.x - E6–E12 (New Class wizard, Find Usages, Go to Declaration, Rename, J2K, New Project, Debugger):
0.11.x+ - Major version
1.0.0: when feature parity with the IDEA plugin reached