Checkpoint - random changes I've had around for a year... not sure wh… #4

Open
darinkelkhoff wants to merge 1 commits from wip/dk-open-changes-as-of-2025-11 into develop
pull from: wip/dk-open-changes-as-of-2025-11
12 changed files with 452 additions and 22 deletions

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.22" />
</component>
</project>
+6 -4
View File
@@ -5,7 +5,7 @@ plugins {
}
group = "com.kingsrook"
version = "1.5.0-SNAPSHOT"
version = "1.4.7-SNAPSHOT"
repositories {
mavenCentral()
@@ -14,7 +14,6 @@ repositories {
}
}
// Configure Gradle IntelliJ Plugin
// Read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
intellij {
@@ -35,8 +34,11 @@ tasks {
}
patchPluginXml {
sinceBuild.set("232")
untilBuild.set("242.*")
sinceBuild.set("241") // note, a previous upload gave us a warning to not include a wildcard here.
// note, a previous upload told us we could just omit this and then would have no "until"...
// but, then, when i built, it seemed to ONLY support the "since" version. So, forget this -
// just live with that warning, and hopefully don't always have to update when IJ does.
untilBuild.set("300.*")
}
signPlugin {
@@ -0,0 +1,128 @@
/*
* Kingsrook IntelliJ Commentator Plugin
* Copyright (C) 2025. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/intellij-commentator-plugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.intellijcommentatorplugin;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListModel;
import java.awt.Component;
import java.awt.Container;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.CheckinProjectPanel;
import com.intellij.openapi.vcs.changes.CommitContext;
import com.intellij.openapi.vcs.checkin.CheckinHandler;
import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
/*******************************************************************************
** todo wip - complete trash - but maybe could be a thing - a hotkey to run this maybe
*******************************************************************************/
public class CommitViewSelectFactory extends CheckinHandlerFactory
{
@Override
public CheckinHandler createHandler(@NotNull CheckinProjectPanel panel, @NotNull CommitContext context)
{
return new CheckinHandler()
{
@Override
@NotNull
public ReturnResult beforeCheckin()
{
ApplicationManager.getApplication().invokeLater(() -> {
Project project = panel.getProject();
VirtualFile[] openFiles = FileEditorManager.getInstance(project).getSelectedFiles();
if(openFiles.length == 0)
{
return;
}
VirtualFile active = openFiles[0];
JComponent root = panel.getComponent();
JList<?> commitList = findJList(root);
if(commitList != null)
{
ListModel<?> model = commitList.getModel();
for(int i = 0; i < model.getSize(); i++)
{
Object element = model.getElementAt(i);
VirtualFile vf = extractVirtualFile(element);
if(vf != null && vf.equals(active))
{
commitList.setSelectedIndex(i);
commitList.ensureIndexIsVisible(i);
break;
}
}
}
});
return ReturnResult.COMMIT;
}
};
}
// Recursively find the JList in the commit UI
private JList<?> findJList(Component c)
{
if(c instanceof JList<?>)
{
return (JList<?>) c;
}
if(c instanceof Container container)
{
for(Component child : container.getComponents())
{
JList<?> result = findJList(child);
if(result != null)
{
return result;
}
}
}
return null;
}
// Attempt to retrieve VirtualFile from the list element (e.g., Change or FilePath)
private VirtualFile extractVirtualFile(Object element)
{
try
{
// adapt based on element types: Change, FilePath, etc.
return (VirtualFile) element.getClass()
.getMethod("getVirtualFile")
.invoke(element);
}
catch(Exception ignored)
{
return null;
}
}
}
@@ -0,0 +1,73 @@
/*
* Kingsrook IntelliJ Commentator Plugin
* Copyright (C) 2025. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/intellij-commentator-plugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.intellijcommentatorplugin;
import com.intellij.lang.documentation.AbstractDocumentationProvider;
import com.intellij.lang.java.JavaDocumentationProvider;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
/*******************************************************************************
* fix the rendering of javadocs in the ide, for when they come from one of our
* header-comments that's full of stars
*******************************************************************************/
public class CustomJavadocProvider extends AbstractDocumentationProvider
{
private final JavaDocumentationProvider javaProvider = new JavaDocumentationProvider();
/***************************************************************************
*
***************************************************************************/
@Override
public String generateDoc(PsiElement element, @Nullable PsiElement originalElement)
{
/////////////////////////////////////////
// Get the standard Java documentation //
/////////////////////////////////////////
String originalDoc = javaProvider.generateDoc(element, originalElement);
if (originalDoc == null)
{
return null;
}
/////////////////////////////////////////////
// Apply your custom formatting/processing //
/////////////////////////////////////////////
return processJavadoc(originalDoc);
}
/***************************************************************************
* If the content starts with a line of stars, strip it away!
***************************************************************************/
private String processJavadoc(String originalDoc)
{
return originalDoc.replaceFirst("""
(<div class='content'>) *\\*{3,}""", "$1");
}
}
@@ -43,6 +43,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.sun.xml.bind.v2.TODO;
import org.apache.commons.lang3.tuple.Pair;
@@ -105,8 +106,8 @@ public class GetSetWithAction extends AbstractKRCommentatorEditorAction
///////////////////////////////////////////////////////////////////////
String selectedLinesText = document.getText(textRange);
PsiElement element = (PsiElement) event.getDataContext().getData("psi.Element");
PsiJavaFile parentOfType = PsiTreeUtil.getParentOfType(element, PsiJavaFile.class);
// PsiElement element = event.getDataContext().getData(CommonDataKeys.PSI_ELEMENT);
// PsiJavaFile parentOfType = PsiTreeUtil.getParentOfType(element, PsiJavaFile.class);
// JavaRecursiveElementWalkingVisitor visitor = new J
@@ -261,7 +262,8 @@ public class GetSetWithAction extends AbstractKRCommentatorEditorAction
return "\n"
+ "\n"
+ " /*******************************************************************************\n"
+ " ** Getter for " + fieldName + "\n"
+ " * Getter for " + fieldName + "\n"
+ " * @see #with" + ucFirst(fieldName) + "(" + fieldType.replaceFirst("<.*", "") + ")\n"
+ " *******************************************************************************/\n"
+ " public " + fieldType + " get" + ucFirst(fieldName) + "()\n"
+ " {\n"
@@ -280,7 +282,8 @@ public class GetSetWithAction extends AbstractKRCommentatorEditorAction
return "\n"
+ "\n"
+ " /*******************************************************************************\n"
+ " ** Setter for " + fieldName + "\n"
+ " * Setter for " + fieldName + "\n"
+ " * @see #with" + ucFirst(fieldName) + "(" + fieldType.replaceFirst("<.*", "") + ")\n"
+ " *******************************************************************************/\n"
+ " public void set" + ucFirst(fieldName) + "(" + fieldType + " " + fieldName + ")\n"
+ " {\n"
@@ -299,7 +302,12 @@ public class GetSetWithAction extends AbstractKRCommentatorEditorAction
return "\n"
+ "\n"
+ " /*******************************************************************************\n"
+ " ** Fluent setter for " + fieldName + "\n"
+ " * Fluent setter for " + fieldName + "\n"
+ " *\n"
+ " * @param " + fieldName + "\n"
+ " * TODO document this property\n"
+ " *\n"
+ " * @return this\n"
+ " *******************************************************************************/\n"
+ " public " + (isStatic ? "void" : className) + " with" + ucFirst(fieldName) + "(" + fieldType + " " + fieldName + ")\n"
+ " {\n"
@@ -167,6 +167,7 @@ public class HeaderCommentAction extends AbstractKRCommentatorEditorAction
rs.append(indent);
rs.append(Objects.requireNonNullElse(subsequentLineIndent, ""));
rs.append(commentChar);
// ... idk... rs.append(commentChar); // todo - option for this? or param??
rs.append(" ");
rs.append("\n");
@@ -0,0 +1,165 @@
/*
* Kingsrook IntelliJ Commentator Plugin
* Copyright (C) 2025. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/intellij-commentator-plugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.intellijcommentatorplugin;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiCodeBlock;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiParserFacade;
import com.intellij.psi.PsiStatement;
import com.intellij.psi.PsiTreeChangeAdapter;
import com.intellij.psi.PsiTreeChangeEvent;
import com.intellij.psi.PsiType;
import com.kingsrook.intellijcommentatorplugin.settings.CommentatorSettingsState;
/*******************************************************************************
** https://claude.ai/share/699ecf53-40ea-4516-ae8a-293e654523b8
*******************************************************************************/
public class MethodCommentInjector extends PsiTreeChangeAdapter
{
@Override
public void childAdded(PsiTreeChangeEvent event)
{
PsiElement child = event.getChild();
CommentatorSettingsState settings = CommentatorSettingsState.getInstance();
if(!settings.autoWriteMethodHeaderCommentsField)
{
return;
}
if(child instanceof PsiMethod)
{
PsiMethod method = (PsiMethod) child;
// Check if this is a new stub method (no body or empty body)
if(isStubMethod(method))
{
addStarComment(method);
}
}
}
private boolean isStubMethod(PsiMethod method)
{
PsiCodeBlock body = method.getBody();
// Interface methods have no body
if(body == null)
{
return true;
}
// Check if body is empty or contains only generated stub code
PsiStatement[] statements = body.getStatements();
if(statements.length == 0)
{
return true;
}
// Check for typical stub patterns like "return null;" or "throw new UnsupportedOperationException();"
if(statements.length == 1)
{
String text = statements[0].getText();
return text.contains("return null") ||
text.contains("UnsupportedOperationException") ||
text.contains("TODO");
}
return false;
}
private void addStarComment(PsiMethod method)
{
Project project = method.getProject();
WriteCommandAction.runWriteCommandAction(project, () -> {
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
String commentText = generateStarComment(method);
// Create a dummy method with the comment to parse it properly
String dummyCode = commentText + "\nvoid dummy() {}";
PsiMethod dummyMethod = factory.createMethodFromText(dummyCode, method);
// Extract the comment from the dummy method
PsiElement firstChild = dummyMethod.getFirstChild();
while(firstChild != null && !(firstChild instanceof PsiComment))
{
firstChild = firstChild.getNextSibling();
}
if(firstChild instanceof PsiComment)
{
PsiComment comment = (PsiComment) firstChild.copy();
// Add comment before the method
PsiElement parent = method.getParent();
parent.addBefore(comment, method);
// Add newline after comment
PsiElement whitespace = PsiParserFacade.getInstance(project)
.createWhiteSpaceFromText("\n ");
parent.addBefore(whitespace, method);
}
});
}
private String generateStarComment(PsiMethod method)
{
StringBuilder sb = new StringBuilder();
String methodName = method.getName();
PsiParameter[] params = method.getParameterList().getParameters();
PsiType returnType = method.getReturnType();
sb.append("""
/***************************************************************************
*
***************************************************************************/
""");
return sb.toString();
}
private String centerText(String text, int width)
{
int padding = (width - text.length()) / 2;
return " ".repeat(padding) + text + " ".repeat(width - text.length() - padding);
}
}
@@ -60,9 +60,15 @@ public class URIDecodeAction extends AbstractKRCommentatorEditorAction
//////////////////////////////////////////////
// Get all the required data from data keys //
//////////////////////////////////////////////
Editor editor = event.getRequiredData(CommonDataKeys.EDITOR);
Editor editor = event.getData(CommonDataKeys.EDITOR);
Project project = event.getProject();
if(editor == null)
{
System.out.println("Null editor - return with noop");
return;
}
///////////////////////////////////////////
// Access document, caret, and selection //
///////////////////////////////////////////
@@ -1,10 +1,10 @@
package com.kingsrook.intellijcommentatorplugin.settings;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.ui.Splitter;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.components.JBLabel;
@@ -18,8 +18,9 @@ import com.intellij.util.ui.FormBuilder;
public class CommentatorSettingsComponent
{
private final JPanel myMainPanel;
private final JBTextField wrapCommentMaxWidthTextField = new JBTextField();
private final JBTextField wrapCommentMinWidthTextField = new JBTextField();
private final JBTextField wrapCommentMaxWidthTextField = new JBTextField();
private final JBTextField wrapCommentMinWidthTextField = new JBTextField();
private final JCheckBox autoWriteMethodHeaderCommentsField = new JCheckBox();
@@ -50,6 +51,13 @@ public class CommentatorSettingsComponent
int indentSize = 20;
myMainPanel = FormBuilder.createFormBuilder()
.addComponent(new TitledSeparator("Header Comments"))
.addComponent(FormBuilder.createFormBuilder()
.setFormLeftIndent(indentSize)
.addLabeledComponent(new JBLabel("Automatically add to generated method stubs: "), autoWriteMethodHeaderCommentsField, 1, false)
.getPanel())
/* todo!
.addComponent(new TitledSeparator("Wrap Comment"))
.addComponent(FormBuilder.createFormBuilder()
.setFormLeftIndent(indentSize)
@@ -62,6 +70,7 @@ public class CommentatorSettingsComponent
.setFormLeftIndent(indentSize)
.addComponentFillVertically(createComponent(), 0)
.getPanel())
*/
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
@@ -129,6 +138,26 @@ public class CommentatorSettingsComponent
/***************************************************************************
**
***************************************************************************/
public void setAutoWriteMethodHeaderCommentsField(boolean newValue)
{
autoWriteMethodHeaderCommentsField.setSelected(newValue);
}
/***************************************************************************
**
***************************************************************************/
public boolean getAutoWriteMethodHeaderCommentsField()
{
return autoWriteMethodHeaderCommentsField.isSelected();
}
private JPanel myMainComponent;
private MyImporterAddEditDeleteListPanel importerPanel;
@@ -189,7 +218,7 @@ public class CommentatorSettingsComponent
Splitter splitter = new Splitter(true);
myMainComponent.add(splitter, BorderLayout.CENTER);
importerPanel = new MyImporterAddEditDeleteListPanel(ApplicationBundle.message("console.fold.console.lines"), ApplicationBundle.message("console.enter.substring.folded"));
importerPanel = new MyImporterAddEditDeleteListPanel("Auto-import these symbols as...", "Enter symbol name and what its import should be:");
// myNegativePanel = new MyAddDeleteListPanel(ApplicationBundle.message("console.fold.exceptions"), ApplicationBundle.message("console.enter.substring.dont.fold"));
splitter.setFirstComponent(importerPanel);
// splitter.setSecondComponent(myNegativePanel);
@@ -63,6 +63,7 @@ public class CommentatorSettingsConfigurable implements Configurable
boolean modified = false;
modified |= !mySettingsComponent.getWrapCommentMaxWidthText().equals(String.valueOf(settings.wrapCommentMaxWidth));
modified |= !mySettingsComponent.getWrapCommentMinWidthText().equals(String.valueOf(settings.wrapCommentMinWidth));
modified |= !mySettingsComponent.getAutoWriteMethodHeaderCommentsField() == settings.autoWriteMethodHeaderCommentsField;
return modified;
}
@@ -78,6 +79,7 @@ public class CommentatorSettingsConfigurable implements Configurable
CommentatorSettingsState settings = CommentatorSettingsState.getInstance();
settings.wrapCommentMaxWidth = Integer.parseInt(mySettingsComponent.getWrapCommentMaxWidthText());
settings.wrapCommentMinWidth = Integer.parseInt(mySettingsComponent.getWrapCommentMinWidthText());
settings.autoWriteMethodHeaderCommentsField = mySettingsComponent.getAutoWriteMethodHeaderCommentsField();
}
@@ -91,6 +93,7 @@ public class CommentatorSettingsConfigurable implements Configurable
CommentatorSettingsState settings = CommentatorSettingsState.getInstance();
mySettingsComponent.setWrapCommentMaxWidthText(String.valueOf(settings.wrapCommentMaxWidth));
mySettingsComponent.setWrapCommentMinWidthText(String.valueOf(settings.wrapCommentMinWidth));
mySettingsComponent.setAutoWriteMethodHeaderCommentsField(settings.autoWriteMethodHeaderCommentsField);
}
@@ -21,6 +21,7 @@ public class CommentatorSettingsState implements PersistentStateComponent<Commen
{
public int wrapCommentMaxWidth = 96;
public int wrapCommentMinWidth = 56;
public boolean autoWriteMethodHeaderCommentsField = true;
+16 -8
View File
@@ -24,8 +24,6 @@
<!-- Unique identifier of the plugin. It should be FQN. It cannot be changed between the plugin versions. -->
<id>com.kingsrook.intellij-commentator-plugin</id>
<version>1.5.0</version>
<!-- Public plugin name should be written in Title Case.
Guidelines: https://plugins.jetbrains.com/docs/marketplace/plugin-overview-page.html#plugin-name -->
<name>Kingsrook Commentator</name>
@@ -75,7 +73,7 @@
or more lines, if you are making a multi-line comment.</li>
<li>To trigger the action, just hit its hotkey / keyboard shortcut. By default, this is <b>F6</b> (but of course you can
customize that under Preferences, Keymap).</li>
<li>Alternatively, you can select it from the <b>Code</b> menu: <b>Create Flower Box Comment</b></li>
<li>Alternatively, you can select it from the Tools → Kingsrook Commentator menu: <b>Create Flower Box Comment</b></li>
</ul>
<p><i>Note that, at this time, only <code>/</code> (slash) is supported as a comment character. Future versions of
this plugin may include language-specific comment characters, and/or preferences to customize the character used.</i></p>
@@ -111,7 +109,7 @@ public Address withCity(String city)
<li>copy the code</li>
<li>paste it</li>
<li>select the pasted code</li>
<li>open <b>SmartSubstitute</b> (from the Edit → Find menu)</li>
<li>open <b>SmartSubstitute</b> (from the Tools → Kingsrook Commentator)</li>
<li>tell it to replace <u>city</u> with <u>state</u></li>
</ul>
<p>The result you'll get is, in the selected code, both the literal values you entered for find and replace will be substituted
@@ -130,8 +128,6 @@ public Address withCity(String city)
<depends>com.intellij.modules.platform</depends>
<depends>com.intellij.modules.java</depends>
<idea-version since-build="222.3345.118"/>
<!-- Extension points defined by the plugin.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
<extensions defaultExtensionNs="com.intellij">
@@ -140,9 +136,17 @@ public Address withCity(String city)
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="com.kingsrook.intellijcommentatorplugin.settings.CommentatorSettingsState"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<!-- PSI listener to detect new methods -->
<psi.treeChangeListener implementation="com.kingsrook.intellijcommentatorplugin.MethodCommentInjector"/>
<checkinHandlerFactory implementation="com.kingsrook.intellijcommentatorplugin.CommitViewSelectFactory"/>
<lang.documentationProvider
language="JAVA"
implementationClass="com.kingsrook.intellijcommentatorplugin.CustomJavadocProvider"
order="first"/>
<applicationConfigurable
parentId="tools"
instance="com.kingsrook.intellijcommentatorplugin.settings.CommentatorSettingsConfigurable"
@@ -150,6 +154,10 @@ public Address withCity(String city)
displayName="Kingsrook Commentator"/>
</extensions>
<projectListeners>
<listener class="com.kingsrook.intellijcommentatorplugin.MethodCommentInjector" topic="com.intellij.psi.PsiTreeChangeListener"/>
</projectListeners>
<actions>
<group id="com.kingsrook.intellijcommentatorplugin.KingsrookCommentatorGroup" text="Kingsrook Commentator" popup="true" icon="/META-INF/pluginMenuIcon.svg">
<add-to-group group-id="ToolsMenu" anchor="last"/>