Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- Added **New → Kotlin Package** for **Source Packages**, **Test Packages**, **Kotlin Source Packages**, and **Kotlin Test Packages**, creating the requested nested package hierarchy exclusively beneath the selected source or test root in Maven, Gradle, and Ant/J2SE projects.
- Fixed Kotlin package nodes under **Kotlin Source Packages** and **Kotlin Test Packages** retaining the standard **Refactor** submenu in the Projects window, so Rename opens **Rename Kotlin Package Directory...** for a non-empty Kotlin package; Java, resource, generated, empty, and non-Kotlin folders retain their existing handling, while package-tree headings are unchanged.
- Added Kotlin filesystem rename commands: choose **Refactor → Rename Kotlin File...** to rename the active `.kt` basename, or right-click a Kotlin-containing folder and choose **Rename Kotlin Package Directory...** to rename the physical directory and all descendants while preserving Kotlin package directives and code references; use **Change Kotlin Package...** for package/reference changes. **Undo Last Refactoring** restores original paths and text. Java file-facade, automatic-renamer, Java/comment/text/index-only, Unicode/quoted-name, and full IDEA project-model cases remain unavailable.
- Added Move Nested Member refactoring: choose **Refactor → Move Nested Member...** on a nested Kotlin class/object or a companion function/property, select a compatible target from a structured package/class tree, and apply the atomic source/target change; nested classes/objects can move into a target class/object without a body, which gains one automatically, while companion functions/properties require an existing companion object. **Undo Last Refactoring** restores both files. Instance members, import aliases, and unvalidated external qualified-use rewrites remain unavailable.
Expand Down
2 changes: 1 addition & 1 deletion CoreImpl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-core-impl</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion KotlinCompilerCliBase/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-compiler-cli-base</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion KotlinFixesImpl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-fixes-impl</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion KotlinFormatter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-formatter</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion KotlinHighlighting/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-highlighting</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion KotlinIcons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-icons</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion KotlinIntentionUtils/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-intention-utils</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion KotlinRefactoring/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-refactoring</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion Nbm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.nbplugins</groupId>
<artifactId>netbeans-plugin-kotlin</artifactId>
<version>0.11.280-SNAPSHOT</version>
<version>0.11.282-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>netbeans-plugin-kotlin-nbm</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright 2026 nbplugins contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*******************************************************************************/
package org.jetbrains.kotlin.file.templates;

import org.jetbrains.kotlin.file.templates.defaultwizard.KtDefaultWizardIterator;
import org.jetbrains.kotlin.file.templates.packagechooser.Type;

/** Creates a Kotlin package directory hierarchy in a selected Kotlin source root. */
public final class KtPackageWizardIterator extends KtDefaultWizardIterator {

/** Creates the Kotlin package wizard. */
public KtPackageWizardIterator() {
super("Kotlin package", Type.PACKAGE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
Expand All @@ -35,7 +35,9 @@
import javax.swing.event.ChangeListener;
import org.jetbrains.kotlin.file.templates.packagechooser.PackageChooser;
import org.jetbrains.kotlin.file.templates.packagechooser.TargetChooserPanel;
import org.jetbrains.kotlin.file.templates.packagechooser.Type;
import org.jetbrains.kotlin.project.KotlinSourceGroup;
import io.github.nbplugins.kotlin.nbm.projectsextensions.KotlinProjectSourceGroups;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
Expand All @@ -54,9 +56,26 @@
public abstract class KtDefaultWizardIterator implements WizardDescriptor.InstantiatingIterator<WizardDescriptor> {

private final String type;
private final Type targetType;

/**
* Creates a wizard that generates a Kotlin file.
*
* @param type display name for the generated Kotlin file type
*/
public KtDefaultWizardIterator(String type) {
this(type, Type.FILE);
}

/**
* Creates a wizard that generates the specified {@code targetType}.
*
* @param type display name for the generated object type
* @param targetType object type created by this wizard
*/
protected KtDefaultWizardIterator(String type, Type targetType) {
this.type = type;
this.targetType = targetType;
}

private int index;
Expand Down Expand Up @@ -87,12 +106,67 @@ private static List<SourceGroup> kotlinSourceGroups(Project project) {
return result;
}

/**
* Returns source groups available to the Kotlin package wizard.
*
* <p>NetBeans exposes both ordinary source and test roots through
* {@link JavaProjectConstants#SOURCES_TYPE_JAVA}; dedicated Kotlin groups
* are appended so the wizard can also target the separated Kotlin trees.
*
* @param project project whose source roots are offered by the package wizard
* @return de-duplicated standard and Kotlin source groups
*/
public static List<SourceGroup> kotlinPackageSourceGroups(Project project) {
Sources sources = ProjectUtils.getSources(project);
List<SourceGroup> kotlinGroups = new ArrayList<>();
List<SourceGroup> result = new ArrayList<>();
if (sources != null) {
result.addAll(Arrays.asList(sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)));
kotlinGroups.addAll(Arrays.asList(sources.getSourceGroups(KotlinProjectSourceGroups.KOTLIN_SOURCE_TYPE)));
kotlinGroups.addAll(Arrays.asList(sources.getSourceGroups(KotlinProjectSourceGroups.KOTLIN_TEST_SOURCE_TYPE)));
}
if (kotlinGroups.isEmpty()) {
kotlinGroups.addAll(kotlinSourceGroups(project));
}
result.addAll(kotlinGroups);
Map<String, SourceGroup> distinctGroups = new LinkedHashMap<>();
for (SourceGroup group : result) {
distinctGroups.putIfAbsent(group.getRootFolder().getPath(), group);
}
return new ArrayList<>(distinctGroups.values());
}

/**
* Creates the directory hierarchy that represents a Kotlin package.
*
* @param root selected Kotlin source root
* @param packageName validated dotted package name
* @return the package directory
* @throws IOException if the folder hierarchy cannot be created
*/
public static FileObject createPackageFolder(FileObject root, String packageName) throws IOException {
FileObject folder = root;
for (String segment : packageName.split("\\.")) {
FileObject child = folder.getFileObject(segment);
if (child == null) {
folder = folder.createFolder(segment);
} else if (child.isFolder()) {
folder = child;
} else {
throw new IOException("Package path is blocked by file: " + child.getPath());
}
}
return folder;
}

private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
if (panels == null) {
Project project = Templates.getProject(wizard);
SourceGroup[] groups;

if (project == null) {

if (targetType == Type.PACKAGE && project != null) {
groups = kotlinPackageSourceGroups(project).toArray(new SourceGroup[0]);
} else if (project == null) {
List<SourceGroup> sourceGroups = Lists.newArrayList();

for (Project proj : OpenProjects.getDefault().getOpenProjects()) {
Expand All @@ -114,7 +188,8 @@ private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
sourceGroups.addAll(kotlinSourceGroups(project));
groups = sourceGroups.toArray(new SourceGroup[0]);
}
packageChooserPanel = PackageChooser.createPackageChooser(project, groups, new KtWizardPanel(), type + " name");
packageChooserPanel = PackageChooser.createPackageChooser(
project, groups, targetType == Type.PACKAGE ? null : new KtWizardPanel(), targetType, type);

panels = new ArrayList<>();
panels.add(packageChooserPanel);
Expand Down Expand Up @@ -160,6 +235,13 @@ public Set<?> instantiate() throws IOException {
dir == null ? "null" : dir.getPath()
});

if (targetType == Type.PACKAGE) {
FileObject createdFolder = createPackageFolder(dir, targetName);
LOG.log(java.util.logging.Level.INFO,
"KtDefaultWizardIterator.instantiate: created package={0}", createdFolder.getPath());
return Collections.singleton(DataObject.find(createdFolder));
}

FileObject createdFile;
try {
String templateBody = template.asText("UTF-8");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,22 @@ public class PackageChooser {

public static String pack = null;

public static TargetChooserPanel createPackageChooser(Project project, SourceGroup[] folders,
WizardDescriptor.Panel<WizardDescriptor> bottomPanel, String type) {
/**
* Creates a target chooser for the supplied source groups.
*
* @param project project that owns the source groups
* @param folders source groups offered by the chooser
* @param bottomPanel optional panel shown below the target chooser
* @param type object type created by the wizard
* @param displayName human-readable name of the created object
* @return configured target chooser panel
*/
public static TargetChooserPanel createPackageChooser(Project project, SourceGroup[] folders,
WizardDescriptor.Panel<WizardDescriptor> bottomPanel, Type type, String displayName) {
if (folders.length == 0) {
throw new IllegalArgumentException("No folders selected");
}
return new TargetChooserPanel(project, folders, bottomPanel, Type.FILE, false, type);
return new TargetChooserPanel(project, folders, bottomPanel, type, false, displayName);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.netbeans.spi.project.ui.PrivilegedTemplates
class KotlinPrivilegedTemplates : PrivilegedTemplates {

override fun getPrivilegedTemplates() = arrayOf(
"Templates/Kotlin/Package",
"Templates/Kotlin/class.kt",
"Templates/Kotlin/interface.kt",
"Templates/Kotlin/dataClass.kt",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ string=String
whitespace=Whitespace
annotation=Annotation
Templates/Kotlin=Kotlin
Templates/Kotlin/Package=Kotlin Package
Templates/Kotlin/class.kt=Kotlin class
Templates/Kotlin/interface.kt=Kotlin interface
Templates/Kotlin/dataClass.kt=Kotlin data class
Expand Down
8 changes: 8 additions & 0 deletions Nbm/src/main/resources/org/jetbrains/kotlin/layer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,14 @@
<attr name="displayName" bundlevalue="org.jetbrains.kotlin.Bundle#Templates/Kotlin"/>
<attr name="position" intvalue="890"/>
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.jetbrains.kotlin.Bundle"/>
<file name="Package">
<attr boolvalue="true" name="template"/>
<attr intvalue="50" name="position"/>
<attr bundlevalue="org.jetbrains.kotlin.Bundle#Templates/Kotlin/Package" name="displayName"/>
<attr name="iconBase" stringvalue="org/jetbrains/kotlin/kt.png"/>
<attr name="instantiatingIterator" newvalue="org.jetbrains.kotlin.file.templates.KtPackageWizardIterator"/>
<attr boolvalue="true" name="requireProject"/>
</file>
<file name="class.kt" url="nbresloc:/org/jetbrains/kotlin/file/templates/class.kt">
<attr boolvalue="true" name="template"/>
<attr intvalue="100" name="position"/>
Expand Down
Loading
Loading