From 1feccf82bce8dc6ba042b3ff260b5b3b13ad8522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Contreras?= Date: Sat, 21 Jan 2023 13:17:23 -0600 Subject: [PATCH 01/13] Tomcat 11 min supported Java is 17 --- .../org/netbeans/modules/tomcat5/j2ee/TomcatPlatformImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise/tomcat5/src/org/netbeans/modules/tomcat5/j2ee/TomcatPlatformImpl.java b/enterprise/tomcat5/src/org/netbeans/modules/tomcat5/j2ee/TomcatPlatformImpl.java index 228cbcae3acc..05e39a684652 100644 --- a/enterprise/tomcat5/src/org/netbeans/modules/tomcat5/j2ee/TomcatPlatformImpl.java +++ b/enterprise/tomcat5/src/org/netbeans/modules/tomcat5/j2ee/TomcatPlatformImpl.java @@ -572,7 +572,7 @@ public Set getSupportedJavaPlatformVersions() { } else { switch (manager.getTomcatVersion()) { case TOMCAT_110: - versions = versionRange(11, 21); + versions = versionRange(17, 21); break; case TOMCAT_101: versions = versionRange(11, 21); From a51b802c590182cb1094b5e52ba95924343995c8 Mon Sep 17 00:00:00 2001 From: John Neffenger Date: Thu, 26 Jan 2023 09:39:04 -0800 Subject: [PATCH 02/13] Import local schema to avoid DNS lookup in build --- .../netbeans/modules/j2ee/dd/impl/resources/jakartaee_10.xsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise/j2ee.dd/src/org/netbeans/modules/j2ee/dd/impl/resources/jakartaee_10.xsd b/enterprise/j2ee.dd/src/org/netbeans/modules/j2ee/dd/impl/resources/jakartaee_10.xsd index 991fcd23eef8..3856cb37a953 100644 --- a/enterprise/j2ee.dd/src/org/netbeans/modules/j2ee/dd/impl/resources/jakartaee_10.xsd +++ b/enterprise/j2ee.dd/src/org/netbeans/modules/j2ee/dd/impl/resources/jakartaee_10.xsd @@ -39,7 +39,7 @@ + schemaLocation="xml.xsd"/> From 3081ac9a1e45568f3641e95c61b95cb734bca455 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Fri, 27 Jan 2023 04:55:00 +0100 Subject: [PATCH 03/13] fix reformatting of annotated records. --- .../modules/java/source/save/Reformatter.java | 6 ++- .../java/source/save/FormatingTest.java | 39 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java index 063fc0a194ee..18a295b99491 100644 --- a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java +++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java @@ -1279,11 +1279,10 @@ private Boolean scanRecord(ClassTree node, Void p) { boolean old = continuationIndent; int oldIndent = indent; try { - continuationIndent = true; ModifiersTree mods = node.getModifiers(); if (mods != null) { if (scan(mods, p)) { - + continuationIndent = true; if (cs.placeNewLineAfterModifiers()) { newline(); } else { @@ -1295,6 +1294,7 @@ private Boolean scanRecord(ClassTree node, Void p) { afterAnnotation = false; } accept(IDENTIFIER); + continuationIndent = true; space(); if (!ERROR.contentEquals(node.getSimpleName())) { @@ -1826,6 +1826,7 @@ public Boolean visitBlock(BlockTree node, Void p) { case CLASS: case ENUM: case INTERFACE: + case RECORD: bracePlacement = cs.getOtherBracePlacement(); if (node.isStatic()) spaceBeforeLeftBrace = cs.spaceBeforeStaticInitLeftBrace(); @@ -5512,6 +5513,7 @@ private int getIndentLevel(TokenSequence tokens, TreePath path) { case CLASS: case ENUM: case INTERFACE: + case RECORD: for (Tree tree : ((ClassTree)path.getLeaf()).getMembers()) { if (tree == lastTree) { indent += tabSize; diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java index c4afa398dd6c..eb663a9d8fa9 100644 --- a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java +++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java @@ -3498,7 +3498,44 @@ public void testMultipleNestingRecordPattern() throws Exception { + "\n"; reformat(doc, content, golden); } - + + public void testAnnotatedRecord() throws Exception { + try { + SourceVersion.valueOf("RELEASE_19"); //NOI18N + } catch (IllegalArgumentException ex) { + //OK, no RELEASE_19, skip test + return; + } + testFile = new File(getWorkDir(), "Test.java"); + TestUtilities.copyStringToFile(testFile, ""); + FileObject testSourceFO = FileUtil.toFileObject(testFile); + DataObject testSourceDO = DataObject.find(testSourceFO); + EditorCookie ec = (EditorCookie) testSourceDO.getLookup().lookup(EditorCookie.class); + final Document doc = ec.openDocument(); + doc.putProperty(Language.class, JavaTokenId.language()); + String content = + "package test;\n" + + "\n" + + "/**\n" + + " * @author duke\n" + + " */\n" + + "@Deprecated public record DeprecatedRecord(int a) {}" + + "\n"; + + String golden = + "package test;\n" + + "\n" + + "/**\n" + + " * @author duke\n" + + " */\n" + + "@Deprecated\n" + + "public record DeprecatedRecord(int a) {\n" + + "\n" + + "}" + + "\n"; + reformat(doc, content, golden); + } + public void testDoWhile() throws Exception { testFile = new File(getWorkDir(), "Test.java"); TestUtilities.copyStringToFile(testFile, From ddf51add9c5da70ac6244c037a1b4f9d10ff4c99 Mon Sep 17 00:00:00 2001 From: Svatopluk Dedic Date: Fri, 27 Jan 2023 09:21:43 +0100 Subject: [PATCH 04/13] Springboot artifacts fix (#5352) * API to create RunConfig for a project-provided action. * Trivial SpringBoot native-image support. --- enterprise/micronaut/nbproject/project.xml | 2 +- .../MicronautPackagingArtifactsImpl.java | 85 +++++++++++++------ .../modules/micronaut/resources/layer.xml | 13 +++ .../resources/spring-actions-maven.xml | 32 +++++++ java/maven/apichanges.xml | 15 ++++ java/maven/nbproject/project.properties | 2 +- .../modules/maven/api/execute/RunUtils.java | 25 ++++++ 7 files changed, 147 insertions(+), 27 deletions(-) create mode 100644 enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/spring-actions-maven.xml diff --git a/enterprise/micronaut/nbproject/project.xml b/enterprise/micronaut/nbproject/project.xml index 51121c770ca6..74638ab53ab9 100644 --- a/enterprise/micronaut/nbproject/project.xml +++ b/enterprise/micronaut/nbproject/project.xml @@ -74,7 +74,7 @@ 2 - 2.156 + 2.157 diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java index b6d8fda6bb7f..4f28b7f07a95 100644 --- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java +++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java @@ -40,6 +40,8 @@ import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectActionContext; import org.netbeans.modules.maven.api.NbMavenProject; +import org.netbeans.modules.maven.api.execute.RunConfig; +import org.netbeans.modules.maven.api.execute.RunUtils; import org.netbeans.modules.micronaut.AbstractMicronautArtifacts; import org.netbeans.modules.project.dependency.ArtifactSpec; import org.netbeans.modules.project.dependency.ProjectArtifactsQuery; @@ -62,8 +64,13 @@ public class MicronautPackagingArtifactsImpl implements ProjectArtifactsImplemen /** * sharedLibrary plugin parameter. Will build a DLL or .so */ - public static final String PLUGIN_PARAM_SHAREDLIBRARY = "sharedLibrary"; + public static final String PLUGIN_PARAM_SHAREDLIBRARY = "sharedLibrary"; // NOI18N + /** + * Maven goal that does the native-image compilation. + */ + private static final String GOAL_NATIVE_COMPILE = "native:compile"; // NOI18N + private static final Set SUPPORTED_ARTIFACT_TYPES = new HashSet<>(Arrays.asList( MicronautMavenConstants.TYPE_DYNAMIC_LIBRARY, MicronautMavenConstants.TYPE_EXECUTABLE )); @@ -116,7 +123,8 @@ public boolean computeSupportsChanges(R r) { return true; } - static class R extends AbstractMicronautArtifacts { + static class R extends AbstractMicronautArtifacts { + private final NbMavenProject mavenProject; public R(Project project, NbMavenProject mavenProject, ProjectArtifactsQuery.Filter query) { @@ -137,11 +145,11 @@ protected void detach(PropertyChangeListener l) { protected boolean accept(PropertyChangeEvent e) { return NbMavenProject.PROP_PROJECT.equals(e.getPropertyName()); } - + @Override protected List compute() { ProjectActionContext buildCtx; - + if (query.getBuildContext() != null) { if (query.getBuildContext().getProjectAction() == null) { buildCtx = query.getBuildContext().newDerivedBuilder().forProjectAction(ActionProvider.COMMAND_BUILD).context(); @@ -152,7 +160,7 @@ protected List compute() { buildCtx = ProjectActionContext.newBuilder(getProject()).forProjectAction(ActionProvider.COMMAND_BUILD).context(); } if (query.getArtifactType() != null && - !SUPPORTED_ARTIFACT_TYPES.contains(query.getArtifactType()) && + !SUPPORTED_ARTIFACT_TYPES.contains(query.getArtifactType()) && !ProjectArtifactsQuery.Filter.TYPE_ALL.equals(query.getArtifactType())) { LOG.log(Level.FINE, "Unsupported type: {0}", query.getArtifactType()); return Collections.emptyList(); @@ -162,7 +170,15 @@ protected List compute() { return Collections.emptyList(); } MavenProject model = mavenProject.getEvaluatedProject(buildCtx); - if (!MicronautMavenConstants.PACKAGING_NATIVE.equals(model.getPackaging())) { + boolean explicitGraalvmGoal = false; + if (buildCtx.getProjectAction() != null) { + RunConfig cfg = RunUtils.createRunConfig(buildCtx.getProjectAction(), getProject(), null, Lookup.EMPTY); + if (cfg != null && cfg.getGoals().contains(GOAL_NATIVE_COMPILE)) { + LOG.log(Level.FINE, "Go explicit native compilation goal from the action"); + explicitGraalvmGoal = true; + } + } + if (!explicitGraalvmGoal && !MicronautMavenConstants.PACKAGING_NATIVE.equals(model.getPackaging())) { LOG.log(Level.FINE, "Unsupported packaging: {0}", model.getPackaging()); return Collections.emptyList(); } @@ -170,6 +186,8 @@ protected List compute() { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Configured build plugins: {0}", model.getBuild().getPlugins()); } + boolean foundExecution = false; + for (Plugin p : model.getBuild().getPlugins()) { if (!(MicronautMavenConstants.NATIVE_BUILD_PLUGIN_GROUP.equals(p.getGroupId()) && MicronautMavenConstants.NATIVE_BUILD_PLUGIN_ID.equals(p.getArtifactId()))) { continue; @@ -179,32 +197,49 @@ protected List compute() { if (pe.getGoals().contains(MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK)) { // NOI18N Xpp3Dom dom = model.getGoalConfiguration(MicronautMavenConstants.NATIVE_BUILD_PLUGIN_GROUP, MicronautMavenConstants.NATIVE_BUILD_PLUGIN_ID, pe.getId(), MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK); // NOI18N if (dom != null) { - Xpp3Dom imageName = dom.getChild(PLUGIN_PARAM_IMAGENAME); // NOI18N - Xpp3Dom sharedLib = dom.getChild(PLUGIN_PARAM_SHAREDLIBRARY); // NOI18N - - String name; - if (imageName == null) { - // project default, but should be injected / interpolated by Maven already. - name = model.getArtifactId(); - } else { - name = imageName.getValue(); - } - - Path full = Paths.get(model.getBuild().getDirectory()).resolve(name); - nativeStuff.add(ArtifactSpec.builder(model.getGroupId(), model.getArtifactId(), model.getVersion(), pe) - .type(sharedLib != null && Boolean.parseBoolean(sharedLib.getValue()) ? MicronautMavenConstants.TYPE_DYNAMIC_LIBRARY : MicronautMavenConstants.TYPE_EXECUTABLE) - .location(full.toUri()) - .forceLocalFile(FileUtil.toFileObject(full.toFile())) - .build() - ); + LOG.log(Level.FINE, "Found bound execution for goals {0}", pe.getGoals()); + addNativeExecutable(nativeStuff, model, dom, pe); + foundExecution = true; } } } } + + if (!foundExecution && explicitGraalvmGoal) { + LOG.log(Level.FINE, "No bound execution found, but explicit native compilation requested, trying to search for plugin base config"); + // try to get the configuration from PluginManagement, since the plugin is not directly in the build sequence. + Plugin p = model.getPluginManagement().getPluginsAsMap().get(MicronautMavenConstants.NATIVE_BUILD_PLUGIN_GROUP + ":" + MicronautMavenConstants.NATIVE_BUILD_PLUGIN_ID); + if (p != null && p.getConfiguration() != null) { + LOG.log(Level.FINE, "Found plugin configuration"); + Xpp3Dom dom = (Xpp3Dom) p.getConfiguration(); + addNativeExecutable(nativeStuff, model, dom, p); + } + } return nativeStuff; } + + private void addNativeExecutable(List nativeStuff, MavenProject model, Xpp3Dom dom, Object data) { + Xpp3Dom imageName = dom.getChild(PLUGIN_PARAM_IMAGENAME); // NOI18N + Xpp3Dom sharedLib = dom.getChild(PLUGIN_PARAM_SHAREDLIBRARY); // NOI18N + + String name; + if (imageName == null) { + // project default, but should be injected / interpolated by Maven already. + name = model.getArtifactId(); + } else { + name = imageName.getValue(); + } + + Path full = Paths.get(model.getBuild().getDirectory()).resolve(name); + nativeStuff.add(ArtifactSpec.builder(model.getGroupId(), model.getArtifactId(), model.getVersion(), data) + .type(sharedLib != null && Boolean.parseBoolean(sharedLib.getValue()) ? MicronautMavenConstants.TYPE_DYNAMIC_LIBRARY : MicronautMavenConstants.TYPE_EXECUTABLE) + .location(full.toUri()) + .forceLocalFile(FileUtil.toFileObject(full.toFile())) + .build() + ); + } } - + @NbBundle.Messages({ "DN_MicronautArtifacts=Micronaut artifact support" }) diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml index 6c8642547844..444894eeb188 100644 --- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml +++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml @@ -80,6 +80,19 @@ + + + + + + + + + + + + + diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/spring-actions-maven.xml b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/spring-actions-maven.xml new file mode 100644 index 000000000000..52f1d71def3b --- /dev/null +++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/spring-actions-maven.xml @@ -0,0 +1,32 @@ + + + + + + native-build + + * + + + native:compile + + + native + + + diff --git a/java/maven/apichanges.xml b/java/maven/apichanges.xml index 3b2f5a33aaf1..8854fb3799e7 100644 --- a/java/maven/apichanges.xml +++ b/java/maven/apichanges.xml @@ -83,6 +83,21 @@ is the proper place. + + + + + + + + + Added a + RunUtils.createRunConfig() variant that allows to create a RunConfig for a project-defined action. + Clients can use this function to use all user customizations that may have been configured for the project action before executing it using + RunUtils.run. + + + LifecycleParticipants can be ignored diff --git a/java/maven/nbproject/project.properties b/java/maven/nbproject/project.properties index eaeea266d4d7..40de3798717b 100644 --- a/java/maven/nbproject/project.properties +++ b/java/maven/nbproject/project.properties @@ -22,7 +22,7 @@ javadoc.apichanges=${basedir}/apichanges.xml javadoc.arch=${basedir}/arch.xml javahelp.hs=maven.hs extra.module.files=maven-nblib/ -spec.version.base: 2.156 +spec.version.base=2.157.0 # The CPExtender test fails in library processing (not randomly) since NetBeans 8.2; disabling. test.excludes=**/CPExtenderTest.class diff --git a/java/maven/src/org/netbeans/modules/maven/api/execute/RunUtils.java b/java/maven/src/org/netbeans/modules/maven/api/execute/RunUtils.java index a007d79b57da..a8d81316bfcb 100644 --- a/java/maven/src/org/netbeans/modules/maven/api/execute/RunUtils.java +++ b/java/maven/src/org/netbeans/modules/maven/api/execute/RunUtils.java @@ -28,11 +28,15 @@ import org.netbeans.api.annotations.common.CheckForNull; import org.netbeans.api.java.source.BuildArtifactMapper; import org.netbeans.api.project.Project; +import org.netbeans.modules.maven.NbMavenProjectImpl; import org.netbeans.modules.maven.api.Constants; +import org.netbeans.modules.maven.execute.ActionToGoalUtils; import org.netbeans.modules.maven.execute.BeanRunConfig; import org.netbeans.modules.maven.execute.MavenCommandLineExecutor; import org.netbeans.spi.project.AuxiliaryProperties; +import org.netbeans.spi.project.ProjectConfiguration; import org.openide.execution.ExecutorTask; +import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; @@ -98,6 +102,27 @@ public void run() { public static ExecutorTask executeMaven(final RunConfig config) { return MavenCommandLineExecutor.executeMaven(config, null, null); } + + /** + * Creates a {@link RunConfig} for the specified project action. Project configuration to be used can be also specified, which + * affects potentially the action's mapping and/or properties. If {@code null} is passed, the current/active configuration is used. + * If applied on non-Maven project, the method returns {@code null}, as well as if the requested action does not exist in the project + * or its requested (or active) configuration. + * + * @param action project action name + * @param prj the project + * @param c the configuration to use, use {@code null} for the active one. + * @param lookup lookup that becomes available to the action provider for possible further data / options + * @return configured {@link RunConfig} suitable for execution or {@code null} if the project is not maven, or action is unavailable. + * @since 2.157 + */ + public static RunConfig createRunConfig(String action, Project prj, ProjectConfiguration c, Lookup lookup) { + NbMavenProjectImpl impl = prj.getLookup().lookup(NbMavenProjectImpl.class); + if (impl == null) { + return null; + } + return ActionToGoalUtils.createRunConfig(action, impl, c, lookup); + } public static RunConfig createRunConfig(File execDir, Project prj, String displayName, List goals) { From d751a932eb3026c64d8f205764ab006da03069c0 Mon Sep 17 00:00:00 2001 From: Svatopluk Dedic Date: Fri, 27 Jan 2023 10:59:14 +0100 Subject: [PATCH 05/13] Proper escaping of TNS_ADMIN path. Select JDBC driver with defined implementation. (#5363) * Proper escaping of TNS_ADMIN path. Select JDBC driver with defined implementation. * Issue warning if driver w/o code locations is selected. --- .../oracle/actions/DownloadWalletAction.java | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java index 2e625f5f8c72..6ebe57c7d964 100644 --- a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java @@ -19,14 +19,16 @@ package org.netbeans.modules.cloud.oracle.actions; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.io.IOException; +import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.text.MessageFormat; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.stream.Collectors; import javax.swing.AbstractAction; import javax.swing.Action; @@ -45,6 +47,8 @@ import org.openide.awt.ActionReferences; import org.openide.awt.ActionRegistration; import org.openide.awt.StatusDisplayer; +import org.openide.filesystems.URLMapper; +import org.openide.util.BaseUtilities; import org.openide.util.ContextAwareAction; import org.openide.util.Exceptions; import org.openide.util.Lookup; @@ -72,11 +76,15 @@ "CTL_DownloadWalletAction=Download Wallet", "MSG_WalletDownloaded=Database Wallet was downloaded to {0}", "MSG_WalletDownloadedPassword=Database Wallet was downloaded. \nGenerated wallet password is: {0}", - "MSG_WalletNoConnection=Wallet doesn't contain any connection" + "MSG_WalletNoConnection=Wallet doesn't contain any connection", + "WARN_DriverWithoutJars=No matching JDBC drivers are configured with code location(s). Driver {0} will be associated with the connection, but the " + + "connection may fail because driver's code is not loadable. Continue ?" + }) public class DownloadWalletAction extends AbstractAction implements ContextAwareAction { + private static final Logger LOG = Logger.getLogger(DownloadWalletAction.class.getName()); - private static final String URL_TEMPLATE = "jdbc:oracle:thin:@{0}?TNS_ADMIN=\"{1}\""; //NOI18N + private static final String URL_TEMPLATE = "jdbc:oracle:thin:@{0}?TNS_ADMIN={1}"; //NOI18N private final DatabaseItem context; private OCIProfile session; @@ -105,7 +113,27 @@ public void actionPerformed(ActionEvent ev) { if (p.getDbUser() != null && p.getDbPassword() != null) { JDBCDriver[] drivers = JDBCDriverManager.getDefault().getDrivers("oracle.jdbc.OracleDriver"); //NOI18N + JDBCDriver jarsPresent = null; + if (drivers.length > 0) { + + // prefer a driver that actually defines some JARs. + for (JDBCDriver d : drivers) { + if (isAvailable(d)) { + jarsPresent = d; + break; + } + } + if (jarsPresent == null) { + jarsPresent = drivers[0]; + LOG.log(Level.WARNING, "Unable to find driver JARs for wallet {0}, using fallback driver: {1}", new Object[] { walletPath, jarsPresent.getName() }); + NotifyDescriptor.Confirmation msg = new NotifyDescriptor.Confirmation(Bundle.WARN_DriverWithoutJars(jarsPresent.getName()), + NotifyDescriptor.WARNING_MESSAGE, NotifyDescriptor.YES_NO_OPTION); + Object choice = DialogDisplayer.getDefault().notify(msg); + if (choice != NotifyDescriptor.YES_OPTION && choice != NotifyDescriptor.OK_OPTION) { + return; + } + } String connectionName = context.getConnectionName(); if (connectionName == null) { Optional n = parseConnectionNames(walletPath).stream().findFirst(); @@ -116,7 +144,7 @@ public void actionPerformed(ActionEvent ev) { return; } } - String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, walletPath); + String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, BaseUtilities.escapeParameters(new String[] { walletPath.toString() })); DatabaseConnection dbConn = DatabaseConnection.create( drivers[0], dbUrl, @@ -127,6 +155,9 @@ public void actionPerformed(ActionEvent ev) { context.getName()); ConnectionManager.getDefault().addConnection(dbConn); } + + // PENDING: what should happen, if the driver is not found at all - display an info message ? + DialogDisplayer.getDefault().notifyLater( new NotifyDescriptor.Message( Bundle.MSG_WalletDownloadedPassword( @@ -140,6 +171,29 @@ public void actionPerformed(ActionEvent ev) { }); } + static boolean isAvailable(JDBCDriver driver) { + URL[] urls = driver.getURLs(); + for (URL u : urls) { + if (URLMapper.findFileObject(u) == null) { + return false; + } + } + if (urls.length > 0) { + // true, some jar is defined && exists. + return true; + } else { + // if the JDBC drive does not list jars, its class must be reachable. DbDriverManager uses no-arg classloader constructor, so it is + // using systemClassLoader as a parent for no-URL URLClassloader. + try { + Class.forName(driver.getClassName(), true, ClassLoader.getSystemClassLoader()); + return true; + } catch (ClassNotFoundException | SecurityException | LinkageError ex) { + // expected, class is not avaialble + return false; + } + } + } + protected List parseConnectionNames(Path wallet) { Path tns = wallet.resolve("tnsnames.ora"); //NOI18N try { From b82df809031696fd24a53bcef309a2b0e8473757 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Sun, 29 Jan 2023 13:43:33 +0100 Subject: [PATCH 06/13] [NETBEANS-4054] Ensuring progress when javac crashes while batch evaluating hints. --- .../netbeans/lib/nbjavac/services/NBAttr.java | 12 ++ .../java/hints/spiimpl/batch/BatchSearch.java | 12 +- .../hints/spiimpl/batch/BatchSearchTest.java | 196 ++++++++++++++---- 3 files changed, 181 insertions(+), 39 deletions(-) diff --git a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java index bca9eb351e6d..4c64615a2b77 100644 --- a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java +++ b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java @@ -43,6 +43,8 @@ */ public class NBAttr extends Attr { + public static boolean TEST_DO_SINGLE_FAIL; + public static void preRegister(Context context) { context.put(attrKey, new Context.Factory() { public Attr make(Context c) { @@ -60,6 +62,16 @@ public NBAttr(Context context) { tm = TreeMaker.instance(context); } + @Override + public void attribClass(DiagnosticPosition pos, ClassSymbol c) { + cancelService.abortIfCanceled(); + if (TEST_DO_SINGLE_FAIL) { + TEST_DO_SINGLE_FAIL = false; + throw new AssertionError("Test requested failure"); + } + super.attribClass(pos, c); + } + @Override public void visitClassDef(JCClassDecl tree) { cancelService.abortIfCanceled(); diff --git a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java index f01480dfa641..b5abcb3f1427 100644 --- a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java +++ b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java @@ -234,8 +234,9 @@ private static void getLocalVerifiedSpans(Collection resourc if (cancel.get()) return; final AtomicBoolean stop = new AtomicBoolean(); + List currentInputList = toProcess.subList(currentPointer.get(), toProcess.size()); // JavaSource js = JavaSource.create(e.getKey(), f); - JavaSource js = JavaSource.create(e.getKey(), toProcess.subList(currentPointer.get(), toProcess.size())); + JavaSource js = JavaSource.create(e.getKey(), currentInputList); js.runUserActionTask(new Task() { @Override @@ -246,8 +247,15 @@ public void run(CompilationController parameter) throws Exception { boolean cont = true; try { - if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) + if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) { + if (currentInputList.size() == 1) { + //the javac crashed while processing the (single) file, we must ensure progress, otherwise infinite loop in processing would happen: + problems.add(new MessageImpl(MessageKind.WARNING, "An error occurred while processing file: " + FileUtil.getFileDisplayName(parameter.getFileObject()) + ", please see the IDE log for more information.")); + currentPointer.incrementAndGet(); + } + return ; + } progress.setMessage("processing: " + FileUtil.getFileDisplayName(parameter.getFileObject())); Resource r = file2Resource.get(parameter.getFileObject()); diff --git a/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java b/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java index a03e88ebee1e..511b4e31145a 100644 --- a/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java +++ b/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java @@ -22,7 +22,6 @@ import org.netbeans.modules.java.hints.spiimpl.MessageImpl; import org.netbeans.modules.java.hints.providers.spi.HintDescription; import java.net.URL; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -35,24 +34,32 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Pattern; +import java.util.function.Consumer; +import java.util.function.Function; import junit.framework.TestSuite; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.classpath.GlobalPathRegistry; import org.netbeans.api.java.classpath.GlobalPathRegistryEvent; import org.netbeans.api.java.classpath.GlobalPathRegistryListener; +import org.netbeans.api.java.source.ClasspathInfo; import org.netbeans.api.java.source.CompilationController; +import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.java.source.JavaSource.Phase; import org.netbeans.api.java.source.SourceUtilsTestUtil; import org.netbeans.core.startup.Main; import org.netbeans.junit.NbTestCase; import org.netbeans.junit.NbTestSuite; import org.netbeans.junit.RandomlyFails; +import org.netbeans.lib.nbjavac.services.NBAttr; import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult; import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Folder; import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Resource; +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.VerifiedSpansCallBack; +import org.netbeans.modules.java.source.BootClassPathUtil; import org.netbeans.modules.parsing.impl.indexing.CacheFolder; import org.netbeans.modules.parsing.impl.indexing.MimeTypes; import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater; +import org.netbeans.modules.parsing.lucene.support.LowMemoryWatcherAccessor; import org.netbeans.spi.editor.hints.ErrorDescription; import org.netbeans.spi.java.classpath.ClassPathProvider; import org.netbeans.spi.java.classpath.support.ClassPathSupport; @@ -293,6 +300,147 @@ public void testBatchSearchFolderNoIndex() throws Exception { assertEquals(golden, output); } + public void testBatchSearchOutOfMemory() throws Exception { + FileObject data = FileUtil.createFolder(workdir, "data"); + FileObject dataSrc1 = FileUtil.createFolder(data, "src1"); + writeFilesAndWaitForScan(dataSrc1, + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"), + new File("test/Test2.java", "package test; public class Test2 { private void test() { java.io.File f = null; f.isDirectory(); } }"), + new File("test/Test3.java", "package test; public class Test3 { private void test() { java.io.File f = null; f.isDirectory(); } }")); + + ClassPathProviderImpl.setSourceRoots(Arrays.asList(dataSrc1)); + + Iterable hints = prepareHints("$1.isDirectory()", "$1", "java.io.File"); + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.specifiedFoldersScope(Folder.convert(data))); + Map> output = new HashMap>(); + + for (Entry> e : result.getResourcesWithRoots().entrySet()) { + Collection resourcesRepr = new HashSet(); + + for (Resource r : e.getValue()) { + resourcesRepr.add(r.getRelativePath()); + } + + output.put(e.getKey().toURL().toExternalForm(), resourcesRepr); + } + + Map> golden = new HashMap>(); + + golden.put(data.toURL().toExternalForm(), new HashSet(Arrays.asList("src1/test/Test1.java", "src1/test/Test2.java", "src1/test/Test3.java"))); + + assertEquals(golden, output); + + //check verification: + Map>> verifiedOutput = verifiedSpans(result, false, c -> new VerifiedSpansCallBack() { + int callbacks; + @Override + public void groupStarted() { + c.groupStarted(); + } + @Override + public boolean spansVerified(CompilationController wc, Resource r, Collection hints) throws Exception { + if (++callbacks == 1) { + LowMemoryWatcherAccessor.setLowMemory(true); + } + return c.spansVerified(wc, r, hints); + } + + @Override + public void groupFinished() { + c.groupFinished(); + } + + @Override + public void cannotVerifySpan(Resource r) { + c.cannotVerifySpan(r); + } + }, errors -> assertEquals(0, errors.size())); + Map>> verifiedGolden = new HashMap>>(); + + Map> verifiedGoldenPart = new HashMap>(); + + verifiedGoldenPart.put("src1/test/Test1.java", Arrays.asList("0:82-0:93:verifier:")); + verifiedGoldenPart.put("src1/test/Test2.java", Arrays.asList("0:82-0:93:verifier:")); + verifiedGoldenPart.put("src1/test/Test3.java", Arrays.asList("0:82-0:93:verifier:")); + + verifiedGolden.put(data.toURL().toExternalForm(), verifiedGoldenPart); + + assertEquals(verifiedGolden, verifiedOutput); + } + + public void testBatchSearchParserCrashProgressEnsured() throws Exception { + writeFilesAndWaitForScan(src1, + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }")); + + Iterable hints = prepareHints("$1.isDirectory()", "$1", "java.io.File"); + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.allOpenedProjectsScope()); + Map> output = new HashMap>(); + + for (Entry> e : result.getResourcesWithRoots().entrySet()) { + Collection resourcesRepr = new HashSet(); + + for (Resource r : e.getValue()) { + resourcesRepr.add(r.getRelativePath()); + } + + output.put(e.getKey().toURL().toExternalForm(), resourcesRepr); + } + + Map> golden = new HashMap>(); + + golden.put(src1.toURL().toExternalForm(), new HashSet(Arrays.asList("test/Test1.java"))); + + assertEquals(golden, output); + + //check verification: + Entry> cpAndFile = BatchUtilities.sortFiles(Arrays.asList(src1.getFileObject("test/Test1.java"))).entrySet().iterator().next(); + JavaSource js = JavaSource.create(cpAndFile.getKey(), cpAndFile.getValue()); + + try { + js.runUserActionTask(cc -> { + NBAttr.TEST_DO_SINGLE_FAIL = true; //the upcoming attribution will fail + cc.toPhase(Phase.RESOLVED); + }, true); + fail("Expected exception not thrown!"); + } catch (IllegalStateException ex) { + //OK + } + + Map>> verifiedOutput = verifiedSpans(result, false, c -> new VerifiedSpansCallBack() { + @Override + public void groupStarted() { + c.groupStarted(); + NBAttr.TEST_DO_SINGLE_FAIL = true; //the upcoming attribution will fail + } + @Override + public boolean spansVerified(CompilationController wc, Resource r, Collection hints) throws Exception { + return c.spansVerified(wc, r, hints); + } + + @Override + public void groupFinished() { + c.groupFinished(); + } + + @Override + public void cannotVerifySpan(Resource r) { + c.cannotVerifySpan(r); + } + }, errors -> { + assertEquals(1, errors.size()); + assertTrue(errors.get(0).text.contains("IDE log")); + }); + + Map>> verifiedGolden = new HashMap>>(); + + assertEquals(verifiedGolden, verifiedOutput); + + //prevent GC: + js.runUserActionTask(cc -> { + assertTrue(true); + }, true); + } + private FileObject workdir; private FileObject src1; private FileObject src2; @@ -332,9 +480,13 @@ private Map> toDebugOutput(BatchResult result) throws E } private Map>> verifiedSpans(BatchResult candidates, boolean doNotRegisterClassPath) throws Exception { + return verifiedSpans(candidates, doNotRegisterClassPath, c -> c, errors -> assertEquals(0, errors.size())); + } + + private Map>> verifiedSpans(BatchResult candidates, boolean doNotRegisterClassPath, Function wrapper, Consumer> validateErrors) throws Exception { final Map>> result = new HashMap>>(); List errors = new LinkedList(); - BatchSearch.getVerifiedSpans(candidates, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() { + BatchSearch.getVerifiedSpans(candidates, new ProgressHandleWrapper(1), wrapper.apply(new VerifiedSpansCallBack() { @Override public void groupStarted() {} @Override @@ -361,7 +513,9 @@ public void groupFinished() {} public void cannotVerifySpan(Resource r) { fail("Cannot verify: " +r.getRelativePath()); } - }, doNotRegisterClassPath, errors, new AtomicBoolean()); + }), doNotRegisterClassPath, errors, new AtomicBoolean()); + + validateErrors.accept(errors); return result; } @@ -382,7 +536,7 @@ public static synchronized Collection getSourceRoots() { @Override public synchronized ClassPath findClassPath(FileObject file, String type) { if (ClassPath.BOOT.equals(type)) { - return ClassPathSupport.createClassPath(getBootClassPath().toArray(new URL[0])); + return BootClassPathUtil.getBootClassPath(); } if (ClassPath.COMPILE.equals(type)) { @@ -402,36 +556,4 @@ public synchronized ClassPath findClassPath(FileObject file, String type) { } - //TODO: copied from SourceUtilsTestUtil: - private static List bootClassPath; - - public static synchronized List getBootClassPath() { - if (bootClassPath == null) { - String cp = System.getProperty("sun.boot.class.path"); - List urls = new ArrayList(); - String[] paths = cp.split(Pattern.quote(System.getProperty("path.separator"))); - - for (String path : paths) { - java.io.File f = new java.io.File(path); - - if (!f.canRead()) - continue; - - FileObject fo = FileUtil.toFileObject(f); - - if (FileUtil.isArchiveFile(fo)) { - fo = FileUtil.getArchiveRoot(fo); - } - - if (fo != null) { - urls.add(fo.toURL()); - } - } - - bootClassPath = urls; - } - - return bootClassPath; - } - } From e8e67fe16eb59263547e6fd66e406a4ee915c82f Mon Sep 17 00:00:00 2001 From: Martin Balin Date: Mon, 30 Jan 2023 09:27:39 +0100 Subject: [PATCH 07/13] VSNetBeans changelog update for 16.0.301 and 17.0 --- java/java.lsp.server/vscode/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/java/java.lsp.server/vscode/CHANGELOG.md b/java/java.lsp.server/vscode/CHANGELOG.md index a7f635f86095..4a070113491b 100644 --- a/java/java.lsp.server/vscode/CHANGELOG.md +++ b/java/java.lsp.server/vscode/CHANGELOG.md @@ -20,6 +20,12 @@ under the License. --> +## Version 16.0.301 +* Multistep wizard added to connect to Autonomous DB +* Fixes for obtaining projects information +* Temporary fix: Support extra cluster directories. +* Support for GraalVM MX projects updated + ## Version 16.0.1 * Gradle 7.6 support to work on JDK 19 * Proxy autodection and configuration for Maven & Gradle From 49a95e98dd9cbe7e84b54b5be6940bdb68a3986d Mon Sep 17 00:00:00 2001 From: Martin Balin Date: Mon, 30 Jan 2023 10:22:24 +0100 Subject: [PATCH 08/13] Mention also 17.0 --- java/java.lsp.server/vscode/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/java.lsp.server/vscode/CHANGELOG.md b/java/java.lsp.server/vscode/CHANGELOG.md index 4a070113491b..2d482521b955 100644 --- a/java/java.lsp.server/vscode/CHANGELOG.md +++ b/java/java.lsp.server/vscode/CHANGELOG.md @@ -20,6 +20,9 @@ under the License. --> +## Version 17.0.0 +* Various bug fixes + ## Version 16.0.301 * Multistep wizard added to connect to Autonomous DB * Fixes for obtaining projects information From 9887c8d848bab74d4db2cd8a7f323c57cb105b87 Mon Sep 17 00:00:00 2001 From: jhorvath Date: Thu, 26 Jan 2023 15:55:33 +0100 Subject: [PATCH 09/13] Use NotifyDescriptor.ComposedInput for Add ADB command (#5353) * Use NotifyDescriptor.ComposedInput for Add ADB command * Fixing steps count, repeat for empty username --- .../cloud/oracle/actions/AddADBAction.java | 144 +++++++++++------- .../oracle/actions/DownloadWalletAction.java | 118 +++++++------- .../oracle/actions/DownloadWalletDialog.java | 2 +- 3 files changed, 151 insertions(+), 113 deletions(-) diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddADBAction.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddADBAction.java index beb96cc5b721..6fd88b62c8f7 100644 --- a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddADBAction.java +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddADBAction.java @@ -21,14 +21,18 @@ import com.oracle.bmc.model.BmcException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import org.netbeans.modules.cloud.oracle.OCIManager; import org.netbeans.modules.cloud.oracle.OCIProfile; +import org.netbeans.modules.cloud.oracle.actions.DownloadWalletDialog.WalletInfo; import org.netbeans.modules.cloud.oracle.compartment.CompartmentItem; import org.netbeans.modules.cloud.oracle.compartment.CompartmentNode; import org.netbeans.modules.cloud.oracle.database.DatabaseItem; @@ -38,11 +42,14 @@ import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.ComposedInput.Callback; +import org.openide.NotifyDescriptor.QuickPick; import org.openide.NotifyDescriptor.QuickPick.Item; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; import org.openide.awt.ActionRegistration; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; /** @@ -65,80 +72,109 @@ "AddADB=Add Oracle Autonomous DB", "SelectTenancy=Select Tenancy", "SelectCompartment=Select Compartment", - "SelectDatabase=Select Database" + "SelectDatabase=Select Compartment or Database", + "EnterUsername=Enter Username", + "EnterPassword=Enter Password" }) public class AddADBAction implements ActionListener { private static final Logger LOGGER = Logger.getLogger(AddADBAction.class.getName()); + private static final String DB = "db"; //NOI18N + private static final String USERNAME = "username"; //NOI18N + private static final String PASSWORD = "password"; //NOI18N @Override public void actionPerformed(ActionEvent e) { - List tenancies = new ArrayList<>(); - for (OCIProfile p : OCIManager.getDefault().getConnectedProfiles()) { - p.getTenancy().ifPresent(tenancies::add); - } - Optional selectedTenancy = chooseOneItem(tenancies, Bundle.SelectTenancy()); - - Optional selectedCompartment = Optional.empty(); - - if (!selectedTenancy.isPresent()) { - return; - } - - List compartments = CompartmentNode.getCompartments().apply(selectedTenancy.get()); - selectedCompartment = chooseOneItem(compartments, Bundle.SelectCompartment()); - DatabaseItem selectedDatabase = null; + Map result = new HashMap<> (); - if (selectedCompartment.isPresent()) { - while(selectedDatabase == null) { - OCIItem item = chooseCopartmentOrDb(selectedCompartment.get()); - if (item == null) { - return; - } - if (item instanceof DatabaseItem) { - selectedDatabase = (DatabaseItem) item; - } - if (item instanceof CompartmentItem) { - selectedCompartment = Optional.of((CompartmentItem) item); + NotifyDescriptor.ComposedInput ci = new NotifyDescriptor.ComposedInput(Bundle.AddADB(), 3, new Callback() { + Map values = new HashMap<> (); + + @Override + public NotifyDescriptor createInput(NotifyDescriptor.ComposedInput input, int number) { + if (number == 1) { + List tenancies = new ArrayList<>(); + for (OCIProfile p : OCIManager.getDefault().getConnectedProfiles()) { + p.getTenancy().ifPresent(tenancies::add); + } + String title; + if (tenancies.size() == 1) { + values.put(1, getCompartmentsAndDbs(tenancies.get(0))); + title = Bundle.SelectCompartment(); + } else { + values.put(1, tenancies); + title = Bundle.SelectTenancy(); + } + return createQuickPick(values.get(1), title); + } else { + NotifyDescriptor prev = input.getInputs()[number - 2]; + OCIItem prevItem = null; + if (prev instanceof NotifyDescriptor.QuickPick) { + Optional selected = ((QuickPick) prev).getItems().stream().filter(item -> item.isSelected()).map(item -> item.getLabel()).findFirst(); + if (selected.isPresent()) { + Optional ti = values.get(number - 1).stream().filter(t -> ((OCIItem) t).getName().equals(selected.get())).findFirst(); + if (ti.isPresent()) { + prevItem = ti.get(); + } + } + if (prevItem instanceof DatabaseItem) { + result.put(DB, prevItem); + return new NotifyDescriptor.InputLine(Bundle.EnterUsername(), Bundle.EnterUsername()); + } + values.put(number, getCompartmentsAndDbs(prevItem)); + input.setEstimatedNumberOfInputs(input.getEstimatedNumberOfInputs() + 1); + return createQuickPick(values.get(number), Bundle.SelectDatabase()); + } else if (prev instanceof NotifyDescriptor.PasswordLine) { + result.put(PASSWORD, ((NotifyDescriptor.PasswordLine) prev).getInputText()); + return null; + } else if (prev instanceof NotifyDescriptor.InputLine) { + String username = ((NotifyDescriptor.InputLine) prev).getInputText(); + if (username == null || username.trim().isEmpty()) { + return prev; + } + result.put(USERNAME, username); + return new NotifyDescriptor.PasswordLine(Bundle.EnterPassword(), Bundle.EnterPassword()); + } + return null; } } - } - if (selectedDatabase != null) { - DownloadWalletAction action = new DownloadWalletAction(selectedDatabase); - action.actionPerformed(null); + + }); + if (DialogDescriptor.OK_OPTION == DialogDisplayer.getDefault().notify(ci)) { + try { + DatabaseItem selectedDatabase = (DatabaseItem) result.get(DB); + DownloadWalletAction action = new DownloadWalletAction(selectedDatabase); + WalletInfo info = new WalletInfo( + DownloadWalletDialog.getWalletsDir().getAbsolutePath(), + AbstractPasswordPanel.generatePassword(), + (String) result.get(USERNAME), + ((String) result.get(PASSWORD)).toCharArray()); + action.addConnection(info); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } } } - private Optional chooseOneItem(List ociItems, String title) { - Optional result = Optional.empty(); - if (ociItems.size() == 1) { - result = Optional.of(ociItems.get(0)); - } else if (ociItems.size() > 0) { - List items = ociItems.stream() - .map(tenancy -> new Item(tenancy.getName(), tenancy.getDescription())) - .collect(Collectors.toList()); - NotifyDescriptor.QuickPick qp = new NotifyDescriptor.QuickPick(title, title, items, false); - if (DialogDescriptor.OK_OPTION == DialogDisplayer.getDefault().notify(qp)) { - Optional selected = qp.getItems().stream().filter(item -> item.isSelected()).map(item -> item.getLabel()).findFirst(); - if (selected.isPresent()) { - result = ociItems.stream().filter(t -> t.getName().equals(selected.get())).findFirst(); - } - - } - } - return result; + private NotifyDescriptor.QuickPick createQuickPick(List ociItems, String title) { + + List items = ociItems.stream() + .map(tenancy -> new Item(tenancy.getName(), tenancy.getDescription())) + .collect(Collectors.toList()); + return new NotifyDescriptor.QuickPick(title, title, items, false); } - - private OCIItem chooseCopartmentOrDb(CompartmentItem compartment) { + private List getCompartmentsAndDbs(OCIItem parent) { List items = new ArrayList<> (); try { - items.addAll(DatabaseNode.getDatabases().apply(compartment)); + if (parent instanceof CompartmentItem) { + items.addAll(DatabaseNode.getDatabases().apply((CompartmentItem) parent)); + } } catch (BmcException e) { LOGGER.log(Level.SEVERE, "Unable to load compartment list", e); // NOI18N } - items.addAll(CompartmentNode.getCompartments().apply(compartment)); - return chooseOneItem(items, Bundle.SelectDatabase()).orElseGet(() -> null); + items.addAll(CompartmentNode.getCompartments().apply(parent)); + return items; } } diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java index 6ebe57c7d964..3e0df5933d39 100644 --- a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java @@ -62,8 +62,8 @@ category = "Tools", id = "org.netbeans.modules.cloud.oracle.actions.DownloadWalletAction" ) -@ActionRegistration( - displayName = "#CTL_DownloadWalletAction", +@ActionRegistration( + displayName = "#CTL_DownloadWalletAction", asynchronous = true, lazy = true ) @@ -107,68 +107,70 @@ public Action createContextAwareInstance(Lookup actionContext) { @Override public void actionPerformed(ActionEvent ev) { Optional result = DownloadWalletDialog.showDialog(context); - result.ifPresent((p) -> { - try { - Path walletPath = session.downloadWallet(context, new String(p.getWalletPassword()), p.getPath()); - if (p.getDbUser() != null && p.getDbPassword() != null) { - - JDBCDriver[] drivers = JDBCDriverManager.getDefault().getDrivers("oracle.jdbc.OracleDriver"); //NOI18N - JDBCDriver jarsPresent = null; - - if (drivers.length > 0) { - - // prefer a driver that actually defines some JARs. - for (JDBCDriver d : drivers) { - if (isAvailable(d)) { - jarsPresent = d; - break; - } + result.ifPresent(p -> addConnection(p)); + } + + void addConnection(DownloadWalletDialog.WalletInfo p) { + try { + Path walletPath = session.downloadWallet(context, new String(p.getWalletPassword()), p.getPath()); + if (p.getDbUser() != null && p.getDbPassword() != null) { + + JDBCDriver[] drivers = JDBCDriverManager.getDefault().getDrivers("oracle.jdbc.OracleDriver"); //NOI18N + JDBCDriver jarsPresent = null; + + if (drivers.length > 0) { + + // prefer a driver that actually defines some JARs. + for (JDBCDriver d : drivers) { + if (isAvailable(d)) { + jarsPresent = d; + break; } - if (jarsPresent == null) { - jarsPresent = drivers[0]; - LOG.log(Level.WARNING, "Unable to find driver JARs for wallet {0}, using fallback driver: {1}", new Object[] { walletPath, jarsPresent.getName() }); - NotifyDescriptor.Confirmation msg = new NotifyDescriptor.Confirmation(Bundle.WARN_DriverWithoutJars(jarsPresent.getName()), - NotifyDescriptor.WARNING_MESSAGE, NotifyDescriptor.YES_NO_OPTION); - Object choice = DialogDisplayer.getDefault().notify(msg); - if (choice != NotifyDescriptor.YES_OPTION && choice != NotifyDescriptor.OK_OPTION) { - return; - } + } + if (jarsPresent == null) { + jarsPresent = drivers[0]; + LOG.log(Level.WARNING, "Unable to find driver JARs for wallet {0}, using fallback driver: {1}", new Object[] { walletPath, jarsPresent.getName() }); + NotifyDescriptor.Confirmation msg = new NotifyDescriptor.Confirmation(Bundle.WARN_DriverWithoutJars(jarsPresent.getName()), + NotifyDescriptor.WARNING_MESSAGE, NotifyDescriptor.YES_NO_OPTION); + Object choice = DialogDisplayer.getDefault().notify(msg); + if (choice != NotifyDescriptor.YES_OPTION && choice != NotifyDescriptor.OK_OPTION) { + return; } - String connectionName = context.getConnectionName(); - if (connectionName == null) { - Optional n = parseConnectionNames(walletPath).stream().findFirst(); - if (n.isPresent()) { - connectionName = n.get(); - } else { - StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletNoConnection()); - return; - } + } + String connectionName = context.getConnectionName(); + if (connectionName == null) { + Optional n = parseConnectionNames(walletPath).stream().findFirst(); + if (n.isPresent()) { + connectionName = n.get(); + } else { + StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletNoConnection()); + return; } - String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, BaseUtilities.escapeParameters(new String[] { walletPath.toString() })); - DatabaseConnection dbConn = DatabaseConnection.create( - drivers[0], - dbUrl, - p.getDbUser(), - p.getDbUser(), - new String(p.getDbPassword()), - true, - context.getName()); - ConnectionManager.getDefault().addConnection(dbConn); } - - // PENDING: what should happen, if the driver is not found at all - display an info message ? - - DialogDisplayer.getDefault().notifyLater( - new NotifyDescriptor.Message( - Bundle.MSG_WalletDownloadedPassword( - new String(p.getWalletPassword())))); - } else { - StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletDownloaded(walletPath.toString())); + String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, BaseUtilities.escapeParameters(new String[] { walletPath.toString() })); + DatabaseConnection dbConn = DatabaseConnection.create( + drivers[0], + dbUrl, + p.getDbUser(), + p.getDbUser(), + new String(p.getDbPassword()), + true, + context.getName()); + ConnectionManager.getDefault().addConnection(dbConn); } - } catch (DatabaseException | IOException ex) { - Exceptions.printStackTrace(ex); + + // PENDING: what should happen, if the driver is not found at all - display an info message ? + + DialogDisplayer.getDefault().notifyLater( + new NotifyDescriptor.Message( + Bundle.MSG_WalletDownloadedPassword( + new String(p.getWalletPassword())))); + } else { + StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletDownloaded(walletPath.toString())); } - }); + } catch (DatabaseException | IOException ex) { + Exceptions.printStackTrace(ex); + } } static boolean isAvailable(JDBCDriver driver) { diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletDialog.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletDialog.java index 3764e305c6a9..6683788ec777 100644 --- a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletDialog.java +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletDialog.java @@ -243,7 +243,7 @@ protected void checkPassword() { checkPasswordLogic(passwd1, passwd2, (m) -> errorMessage(m)); } - private static File getWalletsDir() throws IOException { + static File getWalletsDir() throws IOException { FileObject fo = FileUtil.createFolder(FileUtil.getConfigRoot(), WALLETS_PATH); return FileUtil.toFile(fo); } From 3436a10491f4264c29a154e0858d62f1c3c7ec99 Mon Sep 17 00:00:00 2001 From: Alexey Borokhvostov Date: Thu, 12 Jan 2023 23:42:35 +0700 Subject: [PATCH 10/13] PHP: removed built-in type boolean - deleted the built-in type boolean (php does not have a built-in boolean type: https://www.php.net/manual/en/language.types.intro.php Also see the warning under "Scalar Types": https://www.php.net/manual/en/language.types.declarations.php) - fixed broken tests - fixed issues: - PHP: Generates the return type boolean instead of bool for a method when overriding a base class method with an autocomplete #5283, - PHP: Generates the return type boolean instead of bool for a function in phpDoc #5284 - new tests for fixed issues have been added - does not affect phpDoc --- .../php/editor/actions/UsedNamesCollector.java | 6 +++++- .../modules/php/editor/model/impl/Type.java | 10 +++++++++- .../php/editor/model/impl/VariousUtils.java | 2 +- .../IdenticalComparisonSuggestion.java | 1 - .../unit/data/testfiles/actions/useCase_09.php | 11 +++++++++++ .../testfiles/actions/useCase_09.php.usedNames | 2 ++ .../unit/data/testfiles/actions/useCase_10.php | 11 +++++++++++ .../testfiles/actions/useCase_10.php.usedNames | 2 ++ ...tanceOverrideMethodWithGuessingBoolType.php | 11 +++++++++++ ...errideMethodWithGuessingBoolType_01.codegen | 3 +++ ...errideMethodWithGuessingBoolType_02.codegen | 3 +++ ...issue235450.php.testLowercase_01.completion | 2 +- .../editor/actions/UsedNamesCollectorTest.java | 8 ++++++++ .../SelectedPropertyMethodsCreatorTest.java | 12 ++++++++++++ .../typinghooks/PhpCommentGeneratorTest.java | 18 ++++++++++++++++++ 15 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 php/php.editor/test/unit/data/testfiles/actions/useCase_09.php create mode 100644 php/php.editor/test/unit/data/testfiles/actions/useCase_09.php.usedNames create mode 100644 php/php.editor/test/unit/data/testfiles/actions/useCase_10.php create mode 100644 php/php.editor/test/unit/data/testfiles/actions/useCase_10.php.usedNames create mode 100644 php/php.editor/test/unit/data/testfiles/codegen/testInstanceOverrideMethodWithGuessingBoolType/testInstanceOverrideMethodWithGuessingBoolType.php create mode 100644 php/php.editor/test/unit/data/testfiles/codegen/testInstanceOverrideMethodWithGuessingBoolType/testInstanceOverrideMethodWithGuessingBoolType.php.testInstanceOverrideMethodWithGuessingBoolType_01.codegen create mode 100644 php/php.editor/test/unit/data/testfiles/codegen/testInstanceOverrideMethodWithGuessingBoolType/testInstanceOverrideMethodWithGuessingBoolType.php.testInstanceOverrideMethodWithGuessingBoolType_02.codegen diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java b/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java index e49b3693dd8d..d3286951f768 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java @@ -186,7 +186,7 @@ public void visit(NamespaceName node) { @Override public void visit(PHPDocTypeNode node) { UsedNamespaceName usedName = new UsedNamespaceName(node); - if (isValidTypeName(usedName.getName())) { + if (isValidTypeName(usedName.getName()) && isValidAliasTypeName(usedName.getName())) { processUsedName(usedName); } } @@ -194,6 +194,10 @@ public void visit(PHPDocTypeNode node) { private boolean isValidTypeName(final String typeName) { return !SPECIAL_NAMES.contains(typeName) && !Type.isPrimitive(typeName); } + + private boolean isValidAliasTypeName(final String typeName) { + return !SPECIAL_NAMES.contains(typeName) && !Type.isPrimitiveAlias(typeName); + } private void processUsedName(final UsedNamespaceName usedName) { List usedNames = existingNames.get(usedName.getName()); diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/Type.java b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/Type.java index d17fb1669461..523e6a56b183 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/Type.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/Type.java @@ -108,7 +108,7 @@ private Type() { public static boolean isPrimitive(String typeName) { boolean retval = false; - if (BOOL.equals(typeName) || BOOLEAN.equals(typeName) || INT.equals(typeName) + if (BOOL.equals(typeName) || INT.equals(typeName) || INTEGER.equals(typeName) || FLOAT.equals(typeName) || REAL.equals(typeName) || ARRAY.equals(typeName) || OBJECT.equals(typeName) || MIXED.equals(typeName) || NUMBER.equals(typeName) || CALLBACK.equals(typeName) || RESOURCE.equals(typeName) @@ -120,6 +120,14 @@ public static boolean isPrimitive(String typeName) { } return retval; } + + public static boolean isPrimitiveAlias(String typeName) { + boolean retval = false; + if (BOOLEAN.equals(typeName)) { + retval = true; + } + return retval; + } public static boolean isArray(String typeName) { boolean result = false; diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java index 65bb41e7a5f4..efd84014ca67 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java @@ -435,7 +435,7 @@ static String extractVariableTypeFromExpression(Expression expression, Map diff --git a/php/php.editor/test/unit/data/testfiles/actions/useCase_09.php.usedNames b/php/php.editor/test/unit/data/testfiles/actions/useCase_09.php.usedNames new file mode 100644 index 000000000000..025a53d5833f --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/actions/useCase_09.php.usedNames @@ -0,0 +1,2 @@ +Name: boolean + boolean --> boolean:55 diff --git a/php/php.editor/test/unit/data/testfiles/actions/useCase_10.php b/php/php.editor/test/unit/data/testfiles/actions/useCase_10.php new file mode 100644 index 000000000000..975fa44870cf --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/actions/useCase_10.php @@ -0,0 +1,11 @@ + diff --git a/php/php.editor/test/unit/data/testfiles/actions/useCase_10.php.usedNames b/php/php.editor/test/unit/data/testfiles/actions/useCase_10.php.usedNames new file mode 100644 index 000000000000..8b6a7462f502 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/actions/useCase_10.php.usedNames @@ -0,0 +1,2 @@ +Name: boolean + boolean --> boolean:52 diff --git a/php/php.editor/test/unit/data/testfiles/codegen/testInstanceOverrideMethodWithGuessingBoolType/testInstanceOverrideMethodWithGuessingBoolType.php b/php/php.editor/test/unit/data/testfiles/codegen/testInstanceOverrideMethodWithGuessingBoolType/testInstanceOverrideMethodWithGuessingBoolType.php new file mode 100644 index 000000000000..66c8fb8faaa5 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/codegen/testInstanceOverrideMethodWithGuessingBoolType/testInstanceOverrideMethodWithGuessingBoolType.php @@ -0,0 +1,11 @@ +\n", + "\n"); + } @Override public void insertNewline(String source, String reformatted, IndentPrefs preferences) throws Exception { From 05e0b0feb00022a0540c481bf9e35051fca9340b Mon Sep 17 00:00:00 2001 From: Svata Dedic Date: Tue, 31 Jan 2023 13:57:42 +0100 Subject: [PATCH 11/13] React on both build and compile goals. --- .../maven/MicronautMavenConstants.java | 10 ++++- .../MicronautPackagingArtifactsImpl.java | 37 ++++++++++++++----- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautMavenConstants.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautMavenConstants.java index bc93993b3c05..823347e2b53e 100644 --- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautMavenConstants.java +++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautMavenConstants.java @@ -52,9 +52,15 @@ public final class MicronautMavenConstants { public static final String CLASSIFIER_NATIVE = "native-image"; /** - * Native image plugin's goal to compile image without fork. + * Native image plugin's goal to compile image without fork. Available from + * 0.9.14 version, DOES NOT exist on earlier versions. */ - public static final String PLUGIN_GOAL_COMPILE_NOFORK = "build"; + public static final String PLUGIN_GOAL_COMPILE_NOFORK = "compile-no-fork"; + + /** + * Now deprecated goal, which produces a warning starting from 0.9.14 . + */ + public static final String PLUGIN_GOAL_COMPILE_NOFORK_OLD = "build"; /** * Native image plugin's goal to compile image from commandline diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java index 4f28b7f07a95..f48897160131 100644 --- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java +++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/maven/MicronautPackagingArtifactsImpl.java @@ -66,11 +66,6 @@ public class MicronautPackagingArtifactsImpl implements ProjectArtifactsImplemen */ public static final String PLUGIN_PARAM_SHAREDLIBRARY = "sharedLibrary"; // NOI18N - /** - * Maven goal that does the native-image compilation. - */ - private static final String GOAL_NATIVE_COMPILE = "native:compile"; // NOI18N - private static final Set SUPPORTED_ARTIFACT_TYPES = new HashSet<>(Arrays.asList( MicronautMavenConstants.TYPE_DYNAMIC_LIBRARY, MicronautMavenConstants.TYPE_EXECUTABLE )); @@ -122,6 +117,21 @@ public void handleChangeListener(R r, ChangeListener l, boolean add) { public boolean computeSupportsChanges(R r) { return true; } + + /** + * Goals that actually trigger native artifact generation. As they are compared by name with + * configurations, use both unprefixed and prefixed forms + */ + private static final String[] NATIVE_ARTIFACT_BUILDERS = new String[] { + MicronautMavenConstants.PLUGIN_GOAL_COMPILE, + MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK, + "native:" + MicronautMavenConstants.PLUGIN_GOAL_COMPILE, // NOI18N + "native:" + MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK, // NOI18N + + // Compatibility with plugin 0.9.13 and earlier: + MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK_OLD, + "native:" + MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK_OLD, // NOI18N + }; static class R extends AbstractMicronautArtifacts { @@ -173,9 +183,13 @@ protected List compute() { boolean explicitGraalvmGoal = false; if (buildCtx.getProjectAction() != null) { RunConfig cfg = RunUtils.createRunConfig(buildCtx.getProjectAction(), getProject(), null, Lookup.EMPTY); - if (cfg != null && cfg.getGoals().contains(GOAL_NATIVE_COMPILE)) { - LOG.log(Level.FINE, "Go explicit native compilation goal from the action"); - explicitGraalvmGoal = true; + Set triggerGoals = new HashSet<>(Arrays.asList(NATIVE_ARTIFACT_BUILDERS)); + if (cfg != null) { + triggerGoals.retainAll(cfg.getGoals()); + if (!triggerGoals.isEmpty()) { + LOG.log(Level.FINE, "Go explicit native compilation goal from the action"); + explicitGraalvmGoal = true; + } } } if (!explicitGraalvmGoal && !MicronautMavenConstants.PACKAGING_NATIVE.equals(model.getPackaging())) { @@ -194,8 +208,11 @@ protected List compute() { } LOG.log(Level.FINE, "Configured executions: {0}", p.getExecutions()); for (PluginExecution pe : p.getExecutions()) { - if (pe.getGoals().contains(MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK)) { // NOI18N - Xpp3Dom dom = model.getGoalConfiguration(MicronautMavenConstants.NATIVE_BUILD_PLUGIN_GROUP, MicronautMavenConstants.NATIVE_BUILD_PLUGIN_ID, pe.getId(), MicronautMavenConstants.PLUGIN_GOAL_COMPILE_NOFORK); // NOI18N + Set triggerGoals = new HashSet<>(Arrays.asList(NATIVE_ARTIFACT_BUILDERS)); + triggerGoals.retainAll(pe.getGoals()); + if (!triggerGoals.isEmpty()) { + String goalName = triggerGoals.iterator().next(); + Xpp3Dom dom = model.getGoalConfiguration(MicronautMavenConstants.NATIVE_BUILD_PLUGIN_GROUP, MicronautMavenConstants.NATIVE_BUILD_PLUGIN_ID, pe.getId(), goalName); // NOI18N if (dom != null) { LOG.log(Level.FINE, "Found bound execution for goals {0}", pe.getGoals()); addNativeExecutable(nativeStuff, model, dom, pe); From 6543da0774fe19d0c65aacb1ac71b85234da647c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bl=C3=A4sing?= Date: Wed, 25 Jan 2023 20:57:48 +0100 Subject: [PATCH 12/13] Prevent NullPointerException when caret is not present on text component Observed exception: java.lang.NullPointerException: Cannot invoke "javax.swing.text.Caret.getDot()" because "this.caret" is null at java.desktop/javax.swing.text.JTextComponent.getCaretPosition(JTextComponent.java:1704) at org.netbeans.modules.lsp.client.bindings.MarkOccurrences.(MarkOccurrences.java:71) at org.netbeans.modules.lsp.client.bindings.TextDocumentSyncServerCapabilityHandler.lambda$registerBackgroundTasks$6(TextDocumentSyncServerCapabilityHandler.java:330) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:771) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:741) at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:136) [catch] at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90) --- .../bindings/GoToMarkOccurrencesAction.java | 7 +++- .../lsp/client/bindings/MarkOccurrences.java | 33 ++++++++++++++----- .../RefactoringActionsProvider.java | 13 ++++++-- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/GoToMarkOccurrencesAction.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/GoToMarkOccurrencesAction.java index 4db9dd732a68..daae26127d6a 100644 --- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/GoToMarkOccurrencesAction.java +++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/GoToMarkOccurrencesAction.java @@ -20,6 +20,7 @@ package org.netbeans.modules.lsp.client.bindings; import java.awt.event.ActionEvent; +import javax.swing.text.Caret; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import org.netbeans.api.editor.EditorActionNames; @@ -115,7 +116,11 @@ private static int findOccurrencePosition(boolean directionForward, Document doc private static void navigateToOccurence(boolean next, JTextComponent txt) { if (txt != null && txt.getDocument() != null) { Document doc = txt.getDocument(); - int position = txt.getCaretPosition(); + Caret caret = txt.getCaret(); + if(caret == null) { + return; + } + int position = caret.getDot(); int goTo = findOccurrencePosition(next, doc, position); if (goTo > 0) { txt.setCaretPosition(goTo); diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/MarkOccurrences.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/MarkOccurrences.java index ec628363fcdb..8c94a9e58c5d 100644 --- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/MarkOccurrences.java +++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/MarkOccurrences.java @@ -30,6 +30,7 @@ import javax.swing.event.DocumentListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import org.eclipse.lsp4j.DocumentHighlight; @@ -63,28 +64,33 @@ public class MarkOccurrences implements BackgroundTask, CaretListener, PropertyC private Document doc; private int caretPos; + @SuppressWarnings("LeakingThisInConstructor") public MarkOccurrences(JTextComponent component) { this.component = component; + doc = component.getDocument(); + Caret caret = component.getCaret(); + caretPos = caret != null ? caret.getDot() : -1; component.addCaretListener(this); component.addPropertyChangeListener(this); - doc = component.getDocument(); - caretPos = component.getCaretPosition(); } @Override public void run(LSPBindings bindings, FileObject file) { - Document doc; - int caretPos; + Document localDoc; + int localCaretPos; synchronized (this) { - doc = this.doc; - caretPos = this.caretPos; + localDoc = this.doc; + localCaretPos = this.caretPos; } - getHighlightsBag(doc).setHighlights(computeHighlights(doc, caretPos)); + getHighlightsBag(localDoc).setHighlights(computeHighlights(localDoc, localCaretPos)); } private OffsetsBag computeHighlights(Document doc, int caretPos) { AttributeSet attr = getColoring(doc); OffsetsBag result = new OffsetsBag(doc); + if(caretPos < 0) { + return result; + } FileObject file = NbEditorUtilities.getFileObject(doc); if (file == null) { return result; @@ -128,7 +134,11 @@ private AttributeSet getColoring(Document doc) { @Override public synchronized void caretUpdate(CaretEvent e) { - caretPos = e.getDot(); + if(e != null) { + caretPos = e.getDot(); + } else { + caretPos = -1; + } WORKER.post(() -> { FileObject file = NbEditorUtilities.getFileObject(doc); @@ -149,19 +159,23 @@ static OffsetsBag getHighlightsBag(Document doc) { OffsetsBag bag = (OffsetsBag) doc.getProperty(MarkOccurrences.class); if (bag == null) { - doc.putProperty(MarkOccurrences.class, bag = new OffsetsBag(doc, false)); + bag = new OffsetsBag(doc, false); + doc.putProperty(MarkOccurrences.class, bag); Object stream = doc.getProperty(Document.StreamDescriptionProperty); final OffsetsBag bagFin = bag; DocumentListener l = new DocumentListener() { + @Override public void insertUpdate(DocumentEvent e) { bagFin.removeHighlights(e.getOffset(), e.getOffset(), false); } + @Override public void removeUpdate(DocumentEvent e) { bagFin.removeHighlights(e.getOffset(), e.getOffset(), false); } + @Override public void changedUpdate(DocumentEvent e) { } }; @@ -180,6 +194,7 @@ public void changedUpdate(DocumentEvent e) { @MimeRegistration(mimeType = "", service = HighlightsLayerFactory.class) public static class HighlightsLayerFactoryImpl implements HighlightsLayerFactory { + @Override public HighlightsLayer[] createLayers(HighlightsLayerFactory.Context context) { return new HighlightsLayer[]{ //the mark occurrences layer should be "above" current row and "below" the search layers: diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/refactoring/RefactoringActionsProvider.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/refactoring/RefactoringActionsProvider.java index cf5d4551b187..a369be6927e9 100644 --- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/refactoring/RefactoringActionsProvider.java +++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/refactoring/RefactoringActionsProvider.java @@ -24,6 +24,7 @@ import javax.swing.SwingUtilities; import javax.swing.text.AbstractDocument; import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; import javax.swing.text.Document; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.ReferenceContext; @@ -70,7 +71,11 @@ public void doFindUsages(Lookup lookup) { AbstractDocument abstractDoc = (doc instanceof AbstractDocument) ? ((AbstractDocument) doc) : null; FileObject file = NbEditorUtilities.getFileObject(doc); LSPBindings bindings = LSPBindings.getBindings(file); - int caretPos = c.getCaretPosition(); + Caret caret = c.getCaret(); + if(caret == null) { + return; + } + int caretPos = caret.getDot(); Position pos = Utils.createPosition(doc, caretPos); ReferenceParams params = new ReferenceParams(); params.setTextDocument(new TextDocumentIdentifier(Utils.toURI(file))); @@ -118,7 +123,11 @@ public void doRename(Lookup lookup) { AbstractDocument abstractDoc = (doc instanceof AbstractDocument) ? ((AbstractDocument) doc) : null; FileObject file = NbEditorUtilities.getFileObject(doc); LSPBindings bindings = LSPBindings.getBindings(file); - int caretPos = c.getCaretPosition(); + Caret caret = c.getCaret(); + if(caret == null) { + return; + } + int caretPos = caret.getDot(); Position pos = Utils.createPosition(doc, caretPos); String name; if(abstractDoc != null) { From 11c7a3bd9abf68471982bca00513913817a55d0e Mon Sep 17 00:00:00 2001 From: Johntor Date: Mon, 30 Jan 2023 16:40:25 +0200 Subject: [PATCH 13/13] Fix POM Graph colors for dark themes. Co-authored-by: Michael Bien --- .../modules/java/graph/NodeWidget.java | 90 +++++++++++-------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/java/java.graph/src/org/netbeans/modules/java/graph/NodeWidget.java b/java/java.graph/src/org/netbeans/modules/java/graph/NodeWidget.java index 8a83d5bd4e98..b9cc61a36995 100644 --- a/java/java.graph/src/org/netbeans/modules/java/graph/NodeWidget.java +++ b/java/java.graph/src/org/netbeans/modules/java/graph/NodeWidget.java @@ -20,7 +20,6 @@ import java.awt.Color; import java.awt.Font; -import java.awt.GradientPaint; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; @@ -43,6 +42,8 @@ import org.netbeans.api.visual.widget.LevelOfDetailsWidget; import org.netbeans.api.visual.widget.Scene; import org.netbeans.api.visual.widget.Widget; +import org.netbeans.api.visual.widget.general.IconNodeWidget; +import org.netbeans.api.visual.widget.general.IconNodeWidget.TextOrientation; import static org.netbeans.modules.java.graph.Bundle.ACT_FixVersionConflict; import static org.netbeans.modules.java.graph.Bundle.TIP_MultipleConflict; import static org.netbeans.modules.java.graph.Bundle.TIP_MultipleWarning; @@ -50,8 +51,6 @@ import static org.netbeans.modules.java.graph.Bundle.TIP_SingleWarning; import static org.netbeans.modules.java.graph.DependencyGraphScene.VersionProvider.VERSION_CONFLICT; import static org.netbeans.modules.java.graph.DependencyGraphScene.VersionProvider.VERSION_NO_CONFLICT; -import org.netbeans.api.visual.widget.general.IconNodeWidget; -import org.netbeans.api.visual.widget.general.IconNodeWidget.TextOrientation; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle.Messages; import org.openide.util.Parameters; @@ -67,8 +66,8 @@ class NodeWidget extends Widget implements Ac static final Color DIRECTS_CONFLICT = new Color(235, 88, 194); static final Color DISABLE_HIGHTLIGHT = new Color(255, 255, 194); static final Color HIGHTLIGHT = new Color(255, 255, 129); - static final Color DISABLE_CONFLICT = new Color(219, 155, 153); static final Color CONFLICT = new Color(219, 11, 5); + static final Color DISABLE_CONFLICT = EdgeWidget.deriveColor(CONFLICT, 0.7f); static final Color MANAGED = new Color(30, 255, 150); static final Color WARNING = new Color(255, 150, 20); static final Color DISABLE_WARNING = EdgeWidget.deriveColor(WARNING, 0.7f); @@ -85,6 +84,7 @@ class NodeWidget extends Widget implements Ac private GraphNode node; private boolean readable = false; + private boolean isHighlighted = false; private boolean enlargedFromHover = false; private Timer hoverTimer; @@ -130,7 +130,7 @@ public void select(Widget widget, Point localLocation, boolean invertSelection) } }) : null; this.sceneHoverActionAction = sceneHoverActionAction; - + setLayout(LayoutFactory.createVerticalFlowLayout()); updateTooltip(); @@ -144,7 +144,7 @@ public void select(Widget widget, Point localLocation, boolean invertSelection) hoverBorderC = Color.GRAY; } } - + @Messages({"TIP_Text={0}
{1}", "TIP_SingleConflict=Conflict with {0} version required by {1}", "TIP_SingleWarning=Warning, older version {0} requested by {1}", @@ -206,14 +206,15 @@ private DependencyGraphScene getDependencyGraphScene() { public void highlightText(String searchTerm) { if (searchTerm != null && node.getName().contains(searchTerm)) { - nodeW.setBackground(HIGHTLIGHT); + isHighlighted = true; nodeW.setOpaque(true); setPaintState(EdgeWidget.REGULAR); setReadable(true); } else { //reset - nodeW.setBackground(Color.WHITE); + isHighlighted = false; nodeW.setOpaque(false); + nodeW.getLabelWidget().setForeground(origForeground); setPaintState(EdgeWidget.GRAYED); setReadable(false); } @@ -235,11 +236,11 @@ public int getPaintState () { void setFixed(boolean fixed) { this.fixed = fixed; } - + boolean isFixed() { return fixed; } - + void updatePaintContent() { if (origForeground == null) { origForeground = getForeground(); @@ -254,16 +255,33 @@ void updatePaintContent() { foreC = Color.LIGHT_GRAY; } if (isDisabled) { - foreC = new Color ((int)(foreC.getAlpha() / 1.3f), foreC.getRed(), - foreC.getGreen(), foreC.getBlue()); + foreC = new Color(foreC.getRed(), foreC.getGreen(), foreC.getBlue(), (int) (foreC.getAlpha() / 1.3f)); } } - - contentW.setBorder(BorderFactory.createLineBorder(10, foreC)); nodeW.setForeground(foreC); - if(versionW != null) { + DependencyGraphScene scene = getDependencyGraphScene(); + int conflictType = scene.supportsVersions() ? node.getConflictType(scene::isConflict, scene::compareVersions) : VERSION_NO_CONFLICT; + if (isHighlighted) { + nodeW.getLabelWidget().setForeground(Color.BLACK); + } else { + nodeW.getLabelWidget().setForeground(origForeground); + if (conflictType != VERSION_NO_CONFLICT) { + nodeW.getLabelWidget().setForeground(Color.BLACK); + } else { + int state = node.getManagedState(); + if (GraphNode.OVERRIDES_MANAGED == state) { + nodeW.getLabelWidget().setForeground(Color.BLACK); + } + } + } + contentW.setBorder(BorderFactory.createLineBorder(10, foreC)); + + if (versionW != null) { versionW.setForeground(foreC); } + if (node.isRoot()) { + versionW.setForeground(Color.BLACK); + } if (lockW != null) { lockW.setPaintAsDisabled(paintState == EdgeWidget.GRAYED); lockW.setVisible(!isDisabled); @@ -284,6 +302,8 @@ private void initContent (DependencyGraphScene scene, GraphNodeImplementation im //Artifact name (with optional project icon on the left) nodeW = new IconNodeWidget(scene, TextOrientation.RIGHT_CENTER); nodeW.setLabel(node.getImpl().getQualifiedName() + " "); + nodeW.setBackground(HIGHTLIGHT); + nodeW.setOpaque(false); if (null != icon) { nodeW.setImage(ImageUtilities.icon2Image(icon)); @@ -291,12 +311,14 @@ private void initContent (DependencyGraphScene scene, GraphNodeImplementation im nodeW.getLabelWidget().setUseGlyphVector(true); + Font defF = scene.getDefaultFont(); if (node.isRoot()) { - Font defF = scene.getDefaultFont(); nodeW.getLabelWidget().setFont(defF.deriveFont(Font.BOLD, defF.getSize() + 3f)); + } else { + nodeW.getLabelWidget().setFont(defF); } contentW.addChild(nodeW); - + if(getDependencyGraphScene().supportsVersions()) { Widget versionDetW = new LevelOfDetailsWidget(scene, 0.5, 0.7, Double.MAX_VALUE, Double.MAX_VALUE); versionDetW.setLayout(LayoutFactory.createHorizontalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 2)); @@ -304,6 +326,9 @@ private void initContent (DependencyGraphScene scene, GraphNodeImplementation im versionW = new LabelWidget(scene); versionW.setLabel(scene.getVersion(node.getImpl())); versionW.setUseGlyphVector(true); + if (node.isRoot()) { + versionW.setForeground(Color.BLACK); + } int mngState = node.getManagedState(); if (mngState != GraphNode.UNMANAGED) { lockW = new ImageWidget(scene, @@ -357,19 +382,19 @@ protected void paintBackground() { super.paintBackground(); if (paintState == EdgeWidget.DISABLED) { + nodeW.getLabelWidget().setForeground(origForeground); return; } - DependencyGraphScene scene = getDependencyGraphScene(); Graphics2D g = scene.getGraphics(); Rectangle bounds = getClientArea(); if (node.isRoot()) { - paintBottom(g, bounds, ROOT, Color.WHITE, bounds.height / 2); + paintBottom(g, bounds, ROOT, bounds.height / 2); } else { Color scopeC = scene.getColor(node); - if(scopeC != null) { - paintCorner(RIGHT_BOTTOM, g, bounds, scopeC, Color.WHITE, bounds.width / 2, bounds.height / 2); + if (scopeC != null) { + paintCorner(RIGHT_BOTTOM, g, bounds, scopeC, bounds.width / 2, bounds.height / 2); } int conflictType = scene.supportsVersions() ? node.getConflictType(scene::isConflict, scene::compareVersions) : VERSION_NO_CONFLICT; Color leftTopC = null; @@ -384,11 +409,11 @@ protected void paintBackground() { } } if (leftTopC != null) { - paintCorner(LEFT_TOP, g, bounds, leftTopC, Color.WHITE, bounds.width, bounds.height / 2); + paintCorner(LEFT_TOP, g, bounds, leftTopC, bounds.width, bounds.height / 2); } if (node.getPrimaryLevel() == 1) { - paintBottom(g, bounds, DIRECTS, Color.WHITE, bounds.height / 6); + paintBottom(g, bounds, DIRECTS, bounds.height / 6); } } @@ -397,12 +422,7 @@ protected void paintBackground() { } } - private static void paintCorner (int corner, Graphics2D g, Rectangle bounds, - Color c1, Color c2, int x, int y) { - double h = y*y + x*x; - int gradX = (int)(y*y*x / h); - int gradY = (int)(y*x*x / h); - + private static void paintCorner(int corner, Graphics2D g, Rectangle bounds, Color clr, int x, int y) { Point startPoint = new Point(); Point direction = new Point(); switch (corner) { @@ -433,19 +453,15 @@ private static void paintCorner (int corner, Graphics2D g, Rectangle bounds, default: throw new IllegalArgumentException("Corner id not valid"); //NOI18N } - - g.setPaint(new GradientPaint(startPoint.x, startPoint.y, c1, - startPoint.x + direction.x * gradX, - startPoint.y + direction.y * gradY, c2)); + g.setPaint(clr); g.fillRect( Math.min(startPoint.x, startPoint.x + direction.x * x), Math.min(startPoint.y, startPoint.y + direction.y * y), x, y); } - private static void paintBottom (Graphics2D g, Rectangle bounds, Color c1, Color c2, int thickness) { - g.setPaint(new GradientPaint(bounds.x, bounds.y + bounds.height, c1, - bounds.x, bounds.y + bounds.height - thickness, c2)); + private static void paintBottom(Graphics2D g, Rectangle bounds, Color clr, int thickness) { + g.setPaint(clr); g.fillRect(bounds.x, bounds.y + bounds.height - thickness, bounds.width, thickness); } @@ -484,7 +500,7 @@ protected void notifyStateChanged(ObjectState previousState, ObjectState state) enlargedFromHover = false; } } - + if (previousState.isSelected() != state.isSelected()) { updateNeeded = true; }