diff --git a/.claude/commands/pr.md b/.claude/commands/pr.md index 64c7128..e9aab39 100644 --- a/.claude/commands/pr.md +++ b/.claude/commands/pr.md @@ -46,5 +46,5 @@ Create a branch (if needed), commit staged/unstaged changes, push, and open/upda - Body: formatted using this repo's PR template (`.github/PULL_REQUEST_TEMPLATE.md`), with an additional footer: `🤖 Generated with [Claude Code](https://claude.ai/claude-code)` - Labels — add any that are relevant: - - `bug`, `build`, `ci/cd`, `code-folding`, dependencies`, `enhancement`, `refactor`, `sytax-highlighting` + - `bug`, `build`, `ci/cd`, `dependencies`, `enhancement`, `refactor` - Only add a `tests` label if the PR is *only* adding test coverage diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f276c6f..c3af96a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -37,10 +37,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Set up JDK 17 + - name: Set up JDK 25 uses: actions/setup-java@v5 with: - java-version: '17' + java-version: '25' distribution: 'temurin' # Initializes the CodeQL tools for scanning. diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 0038613..2676546 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -16,14 +16,14 @@ jobs: strategy: matrix: - java: [ '17', '21', '23' ] + java: [ '25', '26' ] steps: - uses: actions/checkout@v6 - name: Verify gradle wrapper - uses: gradle/actions/wrapper-validation@v5 - if: matrix.java == '17' + uses: gradle/actions/wrapper-validation@v6 + if: matrix.java == '25' - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v5 diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AbstractCompletionProvider.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AbstractCompletionProvider.java index 4166b7d..9c777ac 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AbstractCompletionProvider.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AbstractCompletionProvider.java @@ -236,6 +236,13 @@ public boolean removeCompletion(Completion c) { public static class CaseInsensitiveComparator implements Comparator, Serializable { + /** + * Empty constructor. + */ + public CaseInsensitiveComparator() { + // Empty constructor for Javadoc/linting + } + @Override public int compare(Object o1, Object o2) { String s1 = o1 instanceof String ? (String)o1 : diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java index 14ad7f8..4fa0305 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java @@ -283,7 +283,7 @@ protected void doAutocomplete() { */ private static KeyStroke getCopyKeyStroke() { int key = KeyEvent.VK_C; - int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx(); return KeyStroke.getKeyStroke(key, mask); } diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java index 5653c82..b08bac4 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java @@ -10,6 +10,7 @@ import java.awt.*; import java.awt.event.*; +import java.awt.geom.Rectangle2D; import java.beans.*; import java.util.List; import javax.swing.*; @@ -380,8 +381,8 @@ static boolean getDebug() { * @return The default auto-complete trigger key. */ public static KeyStroke getDefaultTriggerKey() { - // Default to CTRL, even on Mac, since Ctrl+Space activates Spotlight - int mask = InputEvent.CTRL_MASK; + // Default to CTRL, even on Mac, since Cmd+Space activates Spotlight + int mask = InputEvent.CTRL_DOWN_MASK; return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, mask); } @@ -865,19 +866,17 @@ protected int refreshPopupWindow() { popupWindow.setCompletions(completions); if (!popupWindow.isVisible()) { - Rectangle r; + Rectangle2D r; try { - r = textComponent.modelToView(textComponent - .getCaretPosition()); + r = textComponent.modelToView2D(textComponent.getCaretPosition()); } catch (BadLocationException ble) { ble.printStackTrace(); return -1; } - Point p = new Point(r.x, r.y); + Point p = new Point((int)r.getX(), (int)r.getY()); SwingUtilities.convertPointToScreen(p, textComponent); - r.x = p.x; - r.y = p.y; - popupWindow.setLocationRelativeTo(r); + Rectangle r2 = new Rectangle(p.x, p.y, (int)r.getWidth(), (int)r.getHeight()); + popupWindow.setLocationRelativeTo(r2); setPopupVisible(true); } @@ -1416,11 +1415,17 @@ public void removeUpdate(DocumentEvent e) { } /** - * The Action that displays the popup window if auto-completion - * is enabled. + * The Action that displays the popup window if auto-completionn is enabled. */ protected class AutoCompleteAction extends AbstractAction { + /** + * Empty constructor. + */ + protected AutoCompleteAction() { + // Empty constructor for Javadoc constructor/linting + } + @Override public void actionPerformed(ActionEvent e) { if (isAutoCompleteEnabled()) { @@ -1486,8 +1491,7 @@ public void actionPerformed(ActionEvent e) { * Listens for events in the parent window of the text component with * auto-completion enabled. */ - private final class ParentWindowListener extends ComponentAdapter implements - WindowFocusListener { + private final class ParentWindowListener extends ComponentAdapter implements WindowFocusListener { public void addTo(Window w) { w.addComponentListener(this); @@ -1558,8 +1562,7 @@ public void uninstall(AutoCompletePopupWindow popupWindow) { /** * Listens for events from the text component we're installed on. */ - private final class TextComponentListener extends FocusAdapter implements - HierarchyListener { + private final class TextComponentListener extends FocusAdapter implements HierarchyListener { void addTo(JTextComponent tc) { tc.addFocusListener(this); diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionCellRenderer.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionCellRenderer.java index a7b5fdb..f2041f9 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionCellRenderer.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionCellRenderer.java @@ -229,7 +229,7 @@ private String createTypeColor() { public void delegateToSubstanceRenderer() throws Exception { Class clazz = Class.forName(SUBSTANCE_RENDERER_CLASS_NAME); DefaultListCellRenderer delegate = - (DefaultListCellRenderer)clazz.newInstance(); + (DefaultListCellRenderer)clazz.getDeclaredConstructor().newInstance(); setDelegateRenderer(delegate); } diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionProviderBase.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionProviderBase.java index 96b5476..c1a033b 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionProviderBase.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/CompletionProviderBase.java @@ -88,6 +88,14 @@ public abstract class CompletionProviderBase implements CompletionProvider { new SortByRelevanceComparator(); + /** + * Empty constructor. + */ + public CompletionProviderBase() { + // Constructor only for no-oart Javadoc comment/linting + } + + @Override public void clearParameterizedCompletionParams() { paramListEnd = paramListStart = 0; diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/DefaultCompletionProvider.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/DefaultCompletionProvider.java index df314e1..a91b420 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/DefaultCompletionProvider.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/DefaultCompletionProvider.java @@ -124,7 +124,7 @@ public String getAlreadyEnteredText(JTextComponent comp) { @Override public List getCompletionsAt(JTextComponent tc, Point p) { - int offset = tc.viewToModel(p); + int offset = tc.viewToModel2D(p); if (offset<0 || offset>=tc.getDocument().getLength()) { lastCompletionsAtText = null; return lastParameterizedCompletionsAt = null; diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletion.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletion.java index 4b05f7c..4720b2b 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletion.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletion.java @@ -160,6 +160,8 @@ public Object getTypeObject() { } /** + * Returns whether this is the last parameter in the completion text. + * * @return Whether this parameter is an "ending parameter;" * that is, whether this parameter is at a logical "ending * point" in the completion text. If the user types in a diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletionContext.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletionContext.java index 0671a52..5a72008 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletionContext.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/ParameterizedCompletionContext.java @@ -17,6 +17,7 @@ import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; @@ -205,12 +206,11 @@ public void activate() { parentWindow, this, ac, pc); try { int dot = tc.getCaretPosition(); - Rectangle r = tc.modelToView(dot); - Point p = new Point(r.x, r.y); + Rectangle2D r = tc.modelToView2D(dot); + Point p = new Point((int)r.getX(), (int)r.getY()); SwingUtilities.convertPointToScreen(p, tc); - r.x = p.x; - r.y = p.y; - tip.setLocationRelativeTo(r); + Rectangle r2 = new Rectangle(p.x, p.y, (int)r.getWidth(), (int)r.getHeight()); + tip.setLocationRelativeTo(r2); tip.setVisible(true); } catch (BadLocationException ble) { // Should never happen UIManager.getLookAndFeel().provideErrorFeedback(tc); @@ -472,7 +472,7 @@ private void installKeyBindings() { oldTabAction = am.get(IM_KEY_TAB); am.put(IM_KEY_TAB, new NextParamAction()); - ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK); + ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK); oldShiftTabKey = im.get(ks); im.put(ks, IM_KEY_SHIFT_TAB); oldShiftTabAction = am.get(IM_KEY_SHIFT_TAB); @@ -674,12 +674,11 @@ private void prepareParamChoicesWindow() { JTextComponent tc = ac.getTextComponent(); try { - Rectangle r = tc.modelToView(offs); - Point p = new Point(r.x, r.y); + Rectangle2D r = tc.modelToView2D(offs); + Point p = new Point((int)r.getX(), (int)r.getY()); SwingUtilities.convertPointToScreen(p, tc); - r.x = p.x; - r.y = p.y; - paramChoicesWindow.setLocationRelativeTo(r); + Rectangle r2 = new Rectangle(p.x, p.y, (int)r.getWidth(), (int)r.getHeight()); + paramChoicesWindow.setLocationRelativeTo(r2); } catch (BadLocationException ble) { // Should never happen UIManager.getLookAndFeel().provideErrorFeedback(tc); ble.printStackTrace(); @@ -770,7 +769,7 @@ private void uninstallKeyBindings() { im.put(ks, oldTabKey); am.put(IM_KEY_TAB, oldTabAction); - ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK); + ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK); im.put(ks, oldShiftTabKey); am.put(IM_KEY_SHIFT_TAB, oldShiftTabAction); diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/SortByRelevanceComparator.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/SortByRelevanceComparator.java index ec2a36f..70d7bf2 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/SortByRelevanceComparator.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/SortByRelevanceComparator.java @@ -22,6 +22,14 @@ */ public class SortByRelevanceComparator implements Comparator, Serializable { + /** + * Compares to {@code CompletionProvider}s by their relevance before sorting them + * lexicographically. + */ + public SortByRelevanceComparator() { + // Do nothing (for Javadoc comment) + } + @Override public int compare(Completion c1, Completion c2) { diff --git a/build.gradle b/build.gradle index 295386e..2d988dc 100644 --- a/build.gradle +++ b/build.gradle @@ -14,12 +14,12 @@ plugins { apply plugin: 'io.github.gradle-nexus.publish-plugin' -// We require building with JDK 17 or later. Built artifact compatibility +// We require building with JDK 25 or later. Built artifact compatibility // is controlled by javaLanguageVersion -assert JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17) +assert JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_25) group = 'com.fifesoft' -// NOTE: Local Java 17: /Library/Java/JavaVirtualMachines/jdk-17.0.13+11/Contents/Home +// NOTE: Local Java 25: /Library/Java/JavaVirtualMachines/jdk-25.0.1+8/Contents/Home allprojects { @@ -31,7 +31,7 @@ allprojects { } wrapper { - gradleVersion = '9.2.1' + gradleVersion = '9.6.1' } } diff --git a/gradle.properties b/gradle.properties index febffc4..4b1635a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Note that Maven- and signing-related properties are in /gradle.properties -javaLanguageVersion=8 +javaLanguageVersion=11 version=3.3.4-SNAPSHOT # Ugh, see https://github.com/gradle/gradle/issues/11308 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee3..b1b8ef5 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 23449a2..a9db115 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index adff685..249efbb 100755 --- a/gradlew +++ b/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/gradlew.bat b/gradlew.bat index e509b2d..8508ef6 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,29 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL%