Repository navigation
Fixed Kotlin refactoring menu and caret restoration #146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ | |
| import org.netbeans.modules.refactoring.spi.ui.UI; | ||
| import org.openide.cookies.EditorCookie; | ||
| import org.openide.filesystems.FileObject; | ||
| import org.openide.loaders.DataObject; | ||
| import org.openide.util.Lookup; | ||
| import org.openide.util.lookup.Lookups; | ||
| import org.openide.windows.TopComponent; | ||
|
|
@@ -55,18 +56,20 @@ | |
| public class KotlinActionsImplementationProvider extends ActionsImplementationProvider { | ||
|
|
||
| /** | ||
| * Returns whether the context is an eligible Kotlin package folder or an open Kotlin editor. | ||
| * Returns whether the context is an eligible Kotlin package folder, physical Kotlin file, or open Kotlin editor. | ||
| * | ||
| * @param lookup lookup supplied by the Refactor action | ||
| * @return {@code true} when this provider owns the Rename operation | ||
| */ | ||
| @Override | ||
| public boolean canRename(Lookup lookup) { | ||
| return KotlinProjectFolderRenameSelection.INSTANCE.resolve(lookup) != null || canRenameEditor(lookup); | ||
| return KotlinProjectFolderRenameSelection.INSTANCE.resolve(lookup) != null | ||
| || selectedKotlinFile(lookup) != null | ||
| || canRenameEditor(lookup); | ||
| } | ||
|
|
||
| /** | ||
| * Opens physical directory rename for Kotlin package folders or symbol rename for Kotlin editors. | ||
| * Opens physical file/directory rename for a project-tree selection or symbol rename for an editor selection. | ||
| * | ||
| * @param lookup lookup supplied by the Refactor action | ||
| */ | ||
|
|
@@ -79,19 +82,54 @@ public void doRename(Lookup lookup) { | |
| } | ||
|
|
||
| EditorCookie ec = lookup.lookup(EditorCookie.class); | ||
| JEditorPane pane = ec.getOpenedPanes()[0]; | ||
| // Use selection start so that renaming a fully-selected word positions inside the word, | ||
| // not past it. When no selection, getSelectionStart() == getCaretPosition(). | ||
| int caretPosition = pane.getSelectionStart(); | ||
| StyledDocument doc = ec.getDocument(); | ||
| FileObject fo = ProjectUtils.getFileObjectForDocument(doc); | ||
| final KtFile ktFile = KotlinPsiManager.INSTANCE.getParsedFile(fo); | ||
| final PsiElement psi = ktFile.findElementAt(caretPosition); | ||
| // Do NOT include fo (FileObject) in the lookup — a built-in NetBeans rename plugin | ||
| // would see it and rename the file on disk instead of renaming the code symbol. | ||
| UI.openRefactoringUI( | ||
| new KotlinRenameRefactoringUI(psi, new RenameRefactoring(Lookups.fixed(psi, doc, caretPosition))), | ||
| TopComponent.getRegistry().getActivated()); | ||
| if (ec != null && ec.getOpenedPanes() != null && ec.getOpenedPanes().length > 0) { | ||
| JEditorPane pane = ec.getOpenedPanes()[0]; | ||
| // Use selection start so that renaming a fully-selected word positions inside the word, | ||
| // not past it. When no selection, getSelectionStart() == getCaretPosition(). | ||
| int caretPosition = pane.getSelectionStart(); | ||
| StyledDocument doc = ec.getDocument(); | ||
| FileObject fo = doc == null ? null : ProjectUtils.getFileObjectForDocument(doc); | ||
| final KtFile ktFile = fo == null ? null : KotlinPsiManager.INSTANCE.getParsedFile(fo); | ||
| final PsiElement psi = ktFile == null ? null : ktFile.findElementAt(caretPosition); | ||
| if (psi != null) { | ||
| // Do NOT include fo (FileObject) in the lookup — a built-in NetBeans rename plugin | ||
| // would see it and rename the file on disk instead of renaming the code symbol. | ||
| UI.openRefactoringUI( | ||
| new KotlinRenameRefactoringUI(psi, new RenameRefactoring(Lookups.fixed(psi, doc, caretPosition))), | ||
| TopComponent.getRegistry().getActivated()); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| FileObject file = selectedKotlinFile(lookup); | ||
| if (file != null) { | ||
| openFileRename(file); | ||
| } | ||
| } | ||
|
|
||
| /** Opens the explicit filesystem rename UI for one Kotlin file selected in a project tree. */ | ||
| private void openFileRename(FileObject file) { | ||
| EventQueue.invokeLater(() -> UI.openRefactoringUI( | ||
| new KotlinFilesystemRenameUI( | ||
| new io.github.nbplugins.kotlin.nbm.refactoring.KotlinRenameFileRefactoring(file, file.getName()), | ||
| false, | ||
| file.getNameExt()), | ||
| TopComponent.getRegistry().getActivated())); | ||
| } | ||
|
|
||
| /** | ||
| * Resolves one physical Kotlin source file from a file-node lookup without requiring an editor. | ||
| * | ||
| * @param lookup lookup supplied by NetBeans | ||
| * @return selected valid Kotlin file, or {@code null} for folders and unrelated selections | ||
| */ | ||
| private FileObject selectedKotlinFile(Lookup lookup) { | ||
| FileObject file = lookup.lookup(FileObject.class); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When at least two unopened Kotlin file nodes are selected, NetBeans' merged node lookup makes Useful? React with 👍 / 👎. |
||
| if (file == null) { | ||
| DataObject dataObject = lookup.lookup(DataObject.class); | ||
| file = dataObject == null ? null : dataObject.getPrimaryFile(); | ||
| } | ||
| return file != null && file.isValid() && !file.isFolder() && file.hasExt("kt") ? file : null; | ||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a Kotlin file is already open and Rename is invoked from its Projects/Files node, that DataNode lookup exposes an
EditorCookiewith nonempty opened panes, so this branch consumes the node request and launches symbol rename at the editor caret instead of reachingselectedKotlinFile()for physical rename. Fresh evidence after the earlier branch-order fix is that an open project node carries both node and editor cookies, so opened-pane state still cannot identify the invocation source; check the selected-node/Explorer context before choosing the editor route.Useful? React with 👍 / 👎.