diff --git a/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/AntSettings.java b/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/AntSettings.java index e7b2b5d84f5e..e3087751ac18 100644 --- a/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/AntSettings.java +++ b/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/AntSettings.java @@ -31,6 +31,7 @@ import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import java.util.regex.Pattern; import org.apache.tools.ant.module.api.IntrospectedInfo; @@ -122,7 +123,27 @@ public static synchronized IntrospectedInfo getCustomDefs() { } public static synchronized void setCustomDefs(IntrospectedInfo ii) { - IntrospectedInfoSerializer.instance.store(prefs().node(PROP_CUSTOM_DEFS), ii); + Preferences prefs = prefs(); + Preferences node = prefs.node(PROP_CUSTOM_DEFS); + try { + IntrospectedInfoSerializer.instance.store(node, ii); + } catch (IllegalArgumentException iae) { + // recreate node in case of corrupted files. Once Preferences are loaded, + // keys which contain code point U+0000 can't be used anymore (clear() will also fail) + if (iae.getMessage().contains("U+0000")) { + LOG.log(Level.WARNING, "recreating {0} preferences node due to code point U+0000", PROP_CUSTOM_DEFS); + try { + node.removeNode(); + prefs.flush(); + node = prefs.node(PROP_CUSTOM_DEFS); + IntrospectedInfoSerializer.instance.store(node, ii); + } catch (BackingStoreException bse) { + throw new RuntimeException("can't write to preferences", bse); + } + } else { + throw iae; + } + } customDefs = ii; } diff --git a/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java b/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java index eec4a7a3fc68..52028c8f841a 100644 --- a/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java +++ b/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java @@ -683,21 +683,21 @@ public IntrospectedInfo load(Preferences node) { try { v = node.get(k, null); } catch (IllegalArgumentException ex) { // e.g invalid code point JDK-8075156 - LOG.log(Level.WARNING, "malformed key: {0}, pref path: {1}, msg: {2}", - new Object[] {k, node.absolutePath(), ex.getMessage()}); + LOG.log(Level.WARNING, "skipping malformed key; pref path: {0}, msg: {1}", + new Object[] {node.absolutePath(), ex.getMessage()}); continue; } assert v != null : k; String[] ss = k.split("\\.", 2); if (ss.length != 2) { - LOG.log(Level.WARNING, "malformed key: {0}, pref path: {1}", new Object[] {k, node.absolutePath()}); + LOG.log(Level.WARNING, "skipping malformed key: {0}, pref path: {1}", new Object[] {k, node.absolutePath()}); continue; } if (ss[0].equals("class")) { Matcher m = p.matcher(ss[1]); boolean match = m.matches(); if (!match) { - LOG.log(Level.WARNING, "malformed key: {0}, pref path: {1}", new Object[] {k, node.absolutePath()}); + LOG.log(Level.WARNING, "skipping malformed key: {0}, pref path: {1}", new Object[] {k, node.absolutePath()}); continue; } String c = m.group(1); diff --git a/ide/git/src/org/netbeans/modules/git/ui/branch/Bundle.properties b/ide/git/src/org/netbeans/modules/git/ui/branch/Bundle.properties index a4c3823428df..bc459fef16b0 100644 --- a/ide/git/src/org/netbeans/modules/git/ui/branch/Bundle.properties +++ b/ide/git/src/org/netbeans/modules/git/ui/branch/Bundle.properties @@ -32,8 +32,9 @@ LBL_DeleteBranchAction.progressName=Deleting Branch {0} LBL_DeleteBranchAction.notMerged=Branch Not Fully Merged MSG_DeleteBranchAction.notMerged=Branch {0} has not been fully merged yet.\n\ Do you still want to delete the branch? +MSG_DeleteBranchAction.noOtherBranches=Repository does not have any other branches LBL_DeleteBranchAction.confirmation=Delete Branch -MSG_DeleteBranchAction.confirmation=Do you really want to delete branch {0} +MSG_DeleteBranchAction.confirmation=Do you really want to delete branch {0}? CreateBranchPanel.cbCheckoutBranch.text=Check&out Created Branch CreateBranchPanel.cbCheckoutBranch.TTtext=Checkout the branch right after it is created diff --git a/ide/git/src/org/netbeans/modules/git/ui/branch/DeleteBranchAction.java b/ide/git/src/org/netbeans/modules/git/ui/branch/DeleteBranchAction.java index 908cc6e6ee14..42282674c09d 100644 --- a/ide/git/src/org/netbeans/modules/git/ui/branch/DeleteBranchAction.java +++ b/ide/git/src/org/netbeans/modules/git/ui/branch/DeleteBranchAction.java @@ -22,7 +22,6 @@ import org.netbeans.modules.git.client.GitClientExceptionHandler; import java.io.File; import java.util.HashMap; -import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.netbeans.libs.git.GitBranch; @@ -38,7 +37,6 @@ import org.openide.NotifyDescriptor; import org.openide.awt.ActionID; import org.openide.awt.ActionRegistration; -import org.openide.nodes.Node; import org.openide.util.NbBundle; /** @@ -58,6 +56,9 @@ protected void performAction(File repository, File[] roots, VCSContext context) branches.remove(info.getActiveBranch().getName()); if (branches.isEmpty()) { + DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message( + NbBundle.getMessage(DeleteBranchAction.class, "MSG_DeleteBranchAction.noOtherBranches") + )); return; } @@ -67,23 +68,6 @@ protected void performAction(File repository, File[] roots, VCSContext context) } } - @Override - protected boolean enable(Node[] activatedNodes) { - if (!super.enable(activatedNodes)) { - return false; - } - - // require 2+ branches - Map.Entry actionRoots = getActionRoots(getCurrentContext(activatedNodes)); - if (actionRoots != null) { - RepositoryInfo info = RepositoryInfo.getInstance(actionRoots.getKey()); - - return info != null && info.getBranches().size() > 1; - } - - return false; - } - public void deleteBranch(final File repository, final String branchName) { NotifyDescriptor nd = new NotifyDescriptor.Confirmation(NbBundle.getMessage(DeleteBranchAction.class, "MSG_DeleteBranchAction.confirmation", branchName), //NOI18N NbBundle.getMessage(DeleteBranchAction.class, "LBL_DeleteBranchAction.confirmation"), //NOI18N diff --git a/ide/git/src/org/netbeans/modules/git/utils/GitUtils.java b/ide/git/src/org/netbeans/modules/git/utils/GitUtils.java index 6b355cc1d607..fef998d88905 100644 --- a/ide/git/src/org/netbeans/modules/git/utils/GitUtils.java +++ b/ide/git/src/org/netbeans/modules/git/utils/GitUtils.java @@ -417,9 +417,8 @@ public static Set getRepositoryRoots (Collection roots) { } /** - * - * @param ctx - * @return + * Returns the repository and its roots. May open a selection dialog if + * there is more than one repository in the provided context. */ public static HashMap.SimpleImmutableEntry getActionRoots(VCSContext ctx) { Set rootsSet = ctx.getRootFiles(); diff --git a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java index 353ad3e69988..9edef9dabc16 100644 --- a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java +++ b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java @@ -338,7 +338,7 @@ public boolean isDependencies() { typeElement = info.getElementUtilities().enclosingTypeElement(el); searchKinds = EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES); } - case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE -> { + case ANNOTATION_TYPE, CLASS, ENUM, RECORD, INTERFACE -> { List topLevelElements = info.getTopLevelElements(); if (topLevelElements.size() == 1 && topLevelElements.get(0) == el) { return false; diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/errors/CreateElementUtilities.java b/java/java.hints/src/org/netbeans/modules/java/hints/errors/CreateElementUtilities.java index d684ad541bf7..f5b1e264a509 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/errors/CreateElementUtilities.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/errors/CreateElementUtilities.java @@ -95,6 +95,7 @@ public final class CreateElementUtilities { private CreateElementUtilities() {} + // TODO rewrite so that it returns List.of() instead of null. Both states (null and .isEmpty()) are handled interchangeably atm. public static List resolveType(Set types, CompilationInfo info, TreePath currentPath, Tree unresolved, int offset, TypeMirror[] typeParameterBound, int[] numTypeParameters) { switch (currentPath.getLeaf().getKind()) { case METHOD: @@ -562,8 +563,13 @@ private static List computeLambdaReturn(Set t return null; } + List resolved = resolveType(types, info, parent.getParentPath(), let, offset, null, null); + if (resolved == null || resolved.isEmpty()) { + return null; + } + List result = new ArrayList<>(); - for (TypeMirror target : resolveType(types, info, parent.getParentPath(), let, offset, null, null)) { + for (TypeMirror target : resolved) { if (!org.netbeans.modules.java.hints.errors.Utilities.isValidType(target) || target.getKind() != TypeKind.DECLARED) { continue; diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/infrastructure/CreatorBasedLazyFixList.java b/java/java.hints/src/org/netbeans/modules/java/hints/infrastructure/CreatorBasedLazyFixList.java index 323c154da5ae..d5d131f297e6 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/infrastructure/CreatorBasedLazyFixList.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/infrastructure/CreatorBasedLazyFixList.java @@ -28,6 +28,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; import org.netbeans.api.java.source.CompilationInfo; import org.netbeans.modules.java.hints.spi.ErrorRule; import org.netbeans.modules.java.hints.spi.ErrorRule.Data; @@ -125,7 +127,15 @@ public void compute(CompilationInfo info, AtomicBoolean cancelled) { data.setData(diagnosticMessage); } - List currentRuleFixes = rule.run(info, diagnosticKey, offset, path, data); + List currentRuleFixes; + + try { + currentRuleFixes = rule.run(info, diagnosticKey, offset, path, data); + } catch (Exception ex) { + Logger.getLogger(CreatorBasedLazyFixList.class.getName()) + .log(Level.WARNING, rule.getDisplayName()+ " rule failed", ex); + continue; + } if (currentRuleFixes == CANCELLED) { cancelled.set(true); diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java index e924a4183b19..9e5daf4b21c4 100644 --- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java @@ -85,4 +85,54 @@ public void testUnusedNoPackagePrivate() throws Exception { .run(Unused.class) .assertWarnings(); } + + public void testNoFixForTopLevelPackagePrivateClass() throws Exception { + HintTest.create() + .input( + """ + package test; + class Test { + } + """) + .run(Unused.class) + .assertWarnings(); + } + + public void testNoFixForTopLevelPackagePrivateEnum() throws Exception { + HintTest.create() + .input( + """ + package test; + enum Test { + } + """) + .run(Unused.class) + .assertWarnings(); + } + + public void testNoFixForTopLevelPackagePrivateInterface() throws Exception { + HintTest.create() + .input( + """ + package test; + interface Test { + } + """) + .run(Unused.class) + .assertWarnings(); + } + + public void testNoFixForTopLevelPackagePrivateRecord() throws Exception { + HintTest.create() + .sourceLevel(17) + .input( + """ + package test; + record Test() { + } + """) + .run(Unused.class) + .assertWarnings(); + } + }