Merge pull request #3121 from apache/delivery
Sync delivery to release125 for 12.5-beta2
diff --git a/enterprise/glassfish.common/src/org/netbeans/modules/glassfish/common/ServerDetails.java b/enterprise/glassfish.common/src/org/netbeans/modules/glassfish/common/ServerDetails.java
index a5ce6a8..d8199f0 100644
--- a/enterprise/glassfish.common/src/org/netbeans/modules/glassfish/common/ServerDetails.java
+++ b/enterprise/glassfish.common/src/org/netbeans/modules/glassfish/common/ServerDetails.java
@@ -209,7 +209,7 @@
*/
GLASSFISH_SERVER_6(NbBundle.getMessage(ServerDetails.class, "STR_6_SERVER_NAME", new Object[]{}), // NOI18N
"deployer:gfv6ee9", // NOI18N
- 6,
+ 600,
"https://repo1.maven.org/maven2/org/glassfish/main/distributions/glassfish/6.0.0/glassfish-6.0.0.zip", // NOI18N
"https://repo1.maven.org/maven2/org/glassfish/main/distributions/glassfish/6.0.0/glassfish-6.0.0.zip", // NOI18N
"http://www.eclipse.org/legal/epl-2.0" //NOI18N
@@ -220,7 +220,7 @@
*/
GLASSFISH_SERVER_6_1_0(NbBundle.getMessage(ServerDetails.class, "STR_610_SERVER_NAME", new Object[]{}), // NOI18N
"deployer:gfv610ee9", // NOI18N
- 6,
+ 610,
"https://repo1.maven.org/maven2/org/glassfish/main/distributions/glassfish/6.1.0/glassfish-6.1.0.zip", // NOI18N
"https://repo1.maven.org/maven2/org/glassfish/main/distributions/glassfish/6.1.0/glassfish-6.1.0.zip", // NOI18N
"http://www.eclipse.org/legal/epl-2.0" //NOI18N
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java b/extide/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java
index 3bf4d48..d11d1ed 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java
@@ -121,11 +121,7 @@
@Override
public String[] getSupportedActions() {
- List<? extends GradleActionsProvider> providers = ActionToTaskUtils.actionProviders(project);
- Set<String> actions = new HashSet<>();
- for (GradleActionsProvider provider : providers) {
- actions.addAll(provider.getSupportedActions());
- }
+ Set<String> actions = new HashSet<>(ActionToTaskUtils.getAllSupportedActions(project));
// add a fixed 'prime build' action
actions.add(ActionProvider.COMMAND_PRIME);
actions.add(COMMAND_DL_SOURCES);
@@ -184,7 +180,7 @@
LOG.log(Level.FINEST, "Priming build action for {0} is: {1}", new Object[] { project, enabled });
return enabled;
}
- return ActionToTaskUtils.isActionEnabled(command, project, context);
+ return ActionToTaskUtils.isActionEnabled(command, null, project, context);
}
@NbBundle.Messages({
@@ -259,7 +255,7 @@
LOG.log(Level.FINE, "Attempt to run a config-disabled action: {0}", action);
return false;
}
- if (!ActionToTaskUtils.isActionEnabled(action, project, context)) {
+ if (!ActionToTaskUtils.isActionEnabled(action, mapping, project, context)) {
LOG.log(Level.FINE, "Attempt to run action that is not enabled: {0}", action);
return false;
}
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/actions/ActionToTaskUtils.java b/extide/gradle/src/org/netbeans/modules/gradle/actions/ActionToTaskUtils.java
index 98c55c6..5c2939d 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/actions/ActionToTaskUtils.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/actions/ActionToTaskUtils.java
@@ -23,7 +23,9 @@
import org.netbeans.modules.gradle.api.execute.ActionMapping;
import org.netbeans.modules.gradle.spi.actions.GradleActionsProvider;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.project.Project;
import org.netbeans.modules.gradle.api.execute.GradleExecConfiguration;
@@ -47,10 +49,43 @@
providers.addAll(Lookup.getDefault().lookupAll(GradleActionsProvider.class));
return providers;
}
-
- public static boolean isActionEnabled(String action, Project project, Lookup lookup) {
- ActionMapping mapping = getActiveMapping(action, project, lookup);
+
+ public static Set<String> getAllSupportedActions(@NonNull Project project) {
+ Set<String> actions = new HashSet<>();
+ for (GradleActionsProvider provider : actionProviders(project)) {
+ actions.addAll(provider.getSupportedActions());
+ }
+ ProjectActionMappingProvider projectProvider = project.getLookup().lookup(ProjectActionMappingProvider.class);
+ ConfigurableActionProvider contextProvider = project.getLookup().lookup(ConfigurableActionProvider.class);
+ ProjectConfigurationProvider<GradleExecConfiguration> pcp = project.getLookup().lookup(ProjectConfigurationProvider.class);
+ if (contextProvider == null || projectProvider == null) {
+ return actions;
+ }
+ if (pcp == null || contextProvider == null) {
+ actions.addAll(projectProvider.customizedActions());
+ } else {
+ for (GradleExecConfiguration gec : pcp.getConfigurations()) {
+ projectProvider = contextProvider.findActionProvider(gec.getId());
+ if (projectProvider != null) {
+ actions.addAll(projectProvider.customizedActions());
+ }
+ }
+ }
+ return actions;
+ }
+
+ public static boolean isCustomMapping(ActionMapping am) {
+ return am.getName().startsWith(ActionMapping.CUSTOM_PREFIX);
+ }
+
+ public static boolean isActionEnabled(String action, ActionMapping mapping, Project project, Lookup lookup) {
+ if (mapping == null) {
+ mapping = getActiveMapping(action, project, lookup);
+ }
if (!ActionMapping.isDisabled(mapping)) {
+ if (isCustomMapping(mapping)) {
+ return true;
+ }
List<? extends GradleActionsProvider> providers = actionProviders(project);
for (GradleActionsProvider provider : providers) {
if (provider.isActionEnabled(action, project, lookup)) {
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImpl.java b/extide/gradle/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImpl.java
index a488d79..3cdee9e 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImpl.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImpl.java
@@ -157,12 +157,7 @@
this.project = project;
this.projectDirectory = project.getProjectDirectory();
- FileChangeListener wl = WeakListeners.create(FileChangeListener.class, new FileChangeAdapter() {
- @Override
- public void fileDataCreated(FileEvent fe) {
- actionFileChanged(fe.getFile(), null, false);
- }
- }, this.projectDirectory);
+ FileChangeListener wl = WeakListeners.create(FileChangeListener.class, fcl, this.projectDirectory);
projectDirectory.addFileChangeListener(wl);
LOG.log(Level.FINER, "Initializing ConfigurableAP for {0}", project);
diff --git a/extide/gradle/test/unit/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImplTest.java b/extide/gradle/test/unit/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImplTest.java
index d63ecd7..5152e08 100644
--- a/extide/gradle/test/unit/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImplTest.java
+++ b/extide/gradle/test/unit/src/org/netbeans/modules/gradle/actions/ConfigurableActionsProviderImplTest.java
@@ -38,10 +38,12 @@
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ui.OpenProjects;
+import org.netbeans.modules.gradle.api.execute.ActionMapping;
import org.netbeans.modules.gradle.api.execute.GradleCommandLine;
import org.netbeans.modules.gradle.api.execute.GradleExecConfiguration;
import org.netbeans.modules.gradle.api.execute.RunConfig;
import org.netbeans.modules.gradle.api.execute.RunUtilsTest;
+import org.netbeans.modules.gradle.customizer.CustomActionMapping;
import org.netbeans.modules.gradle.execute.ConfigPersistenceUtilsTest;
import org.netbeans.modules.gradle.execute.GradleExecAccessor;
import org.netbeans.modules.gradle.execute.GradleExecutor;
@@ -349,4 +351,52 @@
assertTrue("debug.single is supported for java.distribution / default", Arrays.asList(ap.getSupportedActions()).contains("debug.single"));
assertTrue("debug.single is enabled for java.distribution / default", ap.isActionEnabled("debug.single", Lookups.singleton(def)));
}
+
+ /**
+ * Checks that if a custom action is made/paersisted, it will be visible in
+ * action provider.
+ * @throws IOException
+ */
+ @Test
+ public void testSaveCustomizedActionVisible() throws Exception {
+ createGradleProject2();
+
+ CustomActionRegistrationSupport supp = new CustomActionRegistrationSupport(project);
+ CustomActionMapping cam = new CustomActionMapping(ActionMapping.CUSTOM_PREFIX + "1");
+ cam.setArgs("build");
+
+ ActionProvider ap = project.getLookup().lookup(ActionProvider.class);
+ assertFalse(Arrays.asList(ap.getSupportedActions()).contains(cam.getName()));
+
+ supp.registerCustomAction(cam);
+ supp.save();
+
+ assertTrue(Arrays.asList(ap.getSupportedActions()).contains(cam.getName()));
+ }
+
+ /**
+ * Checks that custom created action is enabled.
+ */
+ @Test
+ public void testCustomizedActionEnabled() throws Exception {
+ createGradleProject2();
+
+ CustomActionRegistrationSupport supp = new CustomActionRegistrationSupport(project);
+ CustomActionMapping cam = new CustomActionMapping(ActionMapping.CUSTOM_PREFIX + "1");
+ cam.setArgs("build");
+
+ ActionProvider ap = project.getLookup().lookup(ActionProvider.class);
+
+ assertFalse("Nonexistent ation must not be enabled", ap.isActionEnabled(cam.getName(), Lookup.EMPTY));
+
+ supp.registerCustomAction(cam);
+ supp.save();
+
+ assertTrue("Custom actions are always enabled", ap.isActionEnabled(cam.getName(), Lookup.EMPTY));
+
+ supp.unregisterCustomAction(cam.getName());
+ supp.save();
+
+ assertFalse("Deleted actions must not be enabled", ap.isActionEnabled(cam.getName(), Lookup.EMPTY));
+ }
}
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/ASTUtils.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/ASTUtils.java
index 7027aa4..eee0861 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/ASTUtils.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/ASTUtils.java
@@ -300,7 +300,7 @@
// how to get only methods from source?
// for now, just check line number, if < 0 it is not from source
// Second part of condition is for generated accessors
- if ((!method.isSynthetic() && method.getCode() != null)
+ if ((!method.isSynthetic() && (method.isAbstract() || method.getCode() != null))
|| (method.isSynthetic() && possibleMethods.contains(method.getName()))) {
children.add(method);
}
@@ -353,6 +353,46 @@
return offset;
}
+
+ /**
+ * Returns a simple name for a class. The result is not defined for local and
+ * anonymous classes and for closures.
+ * @param node the class
+ * @return class' simple name
+ */
+ public static String getSimpleName(ClassNode node) {
+ if (node == null) {
+ return null;
+ }
+ if (node.getOuterClass() == null) {
+ return node.getNameWithoutPackage();
+ } else {
+ String s = node.getName().substring(node.getOuterClass().getName().length());
+ if (s.startsWith("$")) {
+ return s.substring(1);
+ } else {
+ return s;
+ }
+ }
+ }
+
+ /**
+ * Returns class' parent's name. For toplevel classes, returns the package name.
+ * For inner classes, it returns the outer class' name. The result is undefined for
+ * local, anonymous classes or closures.
+ * @param node the class node.
+ * @return parent name.
+ */
+ public static String getClassParentName(ClassNode node) {
+ if (node == null) {
+ return null;
+ }
+ if (node.getOuterClass() == null) {
+ return node.getPackageName();
+ } else {
+ return node.getOuterClass().getName();
+ }
+ }
public static ASTNode getForeignNode(final IndexedElement o) {
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/GroovyIndexer.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/GroovyIndexer.java
index 3bbced7..843ddbb 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/GroovyIndexer.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/GroovyIndexer.java
@@ -275,6 +275,7 @@
for (ASTElement child : children) {
switch (child.getKind()) {
+ case INTERFACE:
case CLASS:
analyzeClass((ASTClass) child);
break;
@@ -299,6 +300,10 @@
case FIELD:
indexField((ASTField) child, document);
break;
+ case INTERFACE:
+ case CLASS:
+ analyzeClass((ASTClass) child);
+ break;
}
}
}
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/StructureAnalyzer.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/StructureAnalyzer.java
index d25b468..367206e 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/StructureAnalyzer.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/StructureAnalyzer.java
@@ -73,6 +73,7 @@
private Map<ASTClass, Set<FieldNode>> fields;
private Map<ASTClass, Set<PropertyNode>> properties;
private List<ASTMethod> methods;
+ private Map<String, ASTClass> classes = new HashMap<>();
private static final Logger LOG = Logger.getLogger(StructureAnalyzer.class.getName());
@@ -170,7 +171,10 @@
if (node instanceof ClassNode) {
ClassNode classNode = (ClassNode) node;
ASTClass co = new ASTClass(classNode, classNode.getName());
-
+ classes.put(co.getFqn(), co);
+ if (parent == null && classNode.getOuterClass() != null) {
+ parent = classes.get(classNode.getOuterClass().getName());
+ }
if (parent != null) {
parent.addChild(co);
} else {
@@ -215,7 +219,9 @@
@SuppressWarnings("unchecked")
List<ASTNode> list = ASTUtils.children(node);
-
+
+ // classes are collected from the whole source, but the toplevel classes come
+ // first/earlier than inners.
for (ASTNode child : list) {
path.descend(child);
scan(result, child, path, in, includes, parent);
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/completion/CompletionItem.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/completion/CompletionItem.java
index 71d8fd2..ca59a26 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/completion/CompletionItem.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/completion/CompletionItem.java
@@ -538,6 +538,12 @@
public ElementKind getKind() {
return ElementKind.METHOD;
}
+
+ @Override
+ public int getSortPrioOverride() {
+ // sort meta-methods after normal ones, but before keywords
+ return 550;
+ }
// accessed by CompletionAccessor
List<MethodParameter> getParameters() {
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTClass.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTClass.java
index 2ad7cff..637dd9d 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTClass.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTClass.java
@@ -21,6 +21,7 @@
import org.codehaus.groovy.ast.ClassNode;
import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.groovy.editor.api.ASTUtils;
import org.netbeans.modules.groovy.editor.api.elements.common.ClassElement;
public class ASTClass extends ASTElement implements ClassElement {
@@ -29,14 +30,14 @@
public ASTClass(ClassNode node, String fqn) {
- super(node, node.getPackageName(), node.getNameWithoutPackage());
+ super(node, ASTUtils.getClassParentName(node), ASTUtils.getSimpleName(node));
if (fqn != null) {
this.fqn = fqn;
} else {
this.fqn = getName();
}
}
-
+
@Override
public String getFqn() {
return fqn;
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTField.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTField.java
index 7df4dd7..cefb374 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTField.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTField.java
@@ -23,6 +23,7 @@
import org.codehaus.groovy.ast.FieldNode;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.modules.groovy.editor.api.ASTUtils;
public final class ASTField extends ASTElement {
@@ -33,7 +34,7 @@
public ASTField(FieldNode node, String in, boolean isProperty) {
super(node, in, node.getName());
this.isProperty = isProperty;
- this.fieldType = node.getType().getNameWithoutPackage();
+ this.fieldType = ASTUtils.getSimpleName(node.getType());
}
@Override
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTMethod.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTMethod.java
index 884aa4f..72c4583 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTMethod.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/elements/ast/ASTMethod.java
@@ -22,10 +22,12 @@
import java.util.ArrayList;
import java.util.List;
import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.groovy.editor.api.ASTUtils;
import org.netbeans.modules.groovy.editor.api.elements.common.MethodElement;
public class ASTMethod extends ASTElement implements MethodElement {
@@ -74,7 +76,7 @@
for (Parameter parameter : ((MethodNode) node).getParameters()) {
String paramName = parameter.getName();
String fqnType = parameter.getType().getName();
- String type = parameter.getType().getNameWithoutPackage();
+ String type = ASTUtils.getSimpleName(parameter.getType());
parameters.add(new MethodParameter(fqnType, type, paramName));
}
@@ -115,7 +117,7 @@
public String getName() {
if (name == null) {
if (node instanceof ConstructorNode) {
- name = ((ConstructorNode) node).getDeclaringClass().getNameWithoutPackage();
+ name = ASTUtils.getSimpleName(((ConstructorNode) node).getDeclaringClass());
} else if (node instanceof MethodNode) {
name = ((MethodNode) node).getName();
}
@@ -130,7 +132,7 @@
@Override
public String getReturnType() {
if (returnType == null) {
- returnType = ((MethodNode) node).getReturnType().getNameWithoutPackage();
+ returnType = ASTUtils.getSimpleName(((MethodNode) node).getReturnType());
}
return returnType;
}
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/MethodInference.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/MethodInference.java
index 1ee0e8d..b963917 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/MethodInference.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/MethodInference.java
@@ -19,8 +19,10 @@
package org.netbeans.modules.groovy.editor.completion.inference;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
+import java.util.Queue;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
@@ -70,7 +72,7 @@
ClassNode callerType = findCallerType(methodCall.getObjectExpression(), path, baseDocument, offset);
if (callerType != null) {
- return findReturnTypeFor(callerType, methodCall.getMethodAsString(), methodCall.getArguments(), path, false, baseDocument, offset);
+ return findReturnTypeFor(callerType.redirect(), methodCall.getMethodAsString(), methodCall.getArguments(), path, false, baseDocument, offset);
}
}
@@ -93,7 +95,7 @@
if (expression instanceof StaticMethodCallExpression) {
StaticMethodCallExpression staticMethodCall = (StaticMethodCallExpression) expression;
- return findReturnTypeFor(staticMethodCall.getOwnerType(), staticMethodCall.getMethod(), staticMethodCall.getArguments(), path, true, baseDocument, offset);
+ return findReturnTypeFor(staticMethodCall.getOwnerType().redirect(), staticMethodCall.getMethod(), staticMethodCall.getArguments(), path, true, baseDocument, offset);
}
return null;
}
@@ -141,7 +143,7 @@
}
}
}
-
+
MethodNode possibleMethod = tryFindPossibleMethod(callerType, methodName, paramTypes, isStatic);
if (possibleMethod != null) {
return possibleMethod.getReturnType();
@@ -154,7 +156,13 @@
MethodNode res = null;
ClassNode node = callerType;
- do {
+ Queue<ClassNode> tq = new ArrayDeque<>();
+ tq.add(callerType.redirect());
+ while ((node = tq.poll()) != null) {
+ for (ClassNode in : node.getInterfaces()) {
+ // search also in interfaces
+ tq.add(in.redirect());
+ }
for (MethodNode method : node.getMethods(methodName)) {
if (isStatic && !method.isStatic()) {
continue;
@@ -194,7 +202,10 @@
}
}
node = node.getSuperClass();
- } while (node != null);
+ if (node != null) {
+ tq.add(node.redirect());
+ }
+ };
return res;
}
diff --git a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/TypeInferenceVisitor.java b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/TypeInferenceVisitor.java
index 99573f9..01d3c51 100644
--- a/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/TypeInferenceVisitor.java
+++ b/groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/completion/inference/TypeInferenceVisitor.java
@@ -20,6 +20,7 @@
package org.netbeans.modules.groovy.editor.completion.inference;
import groovy.lang.Range;
+import java.util.Iterator;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
@@ -38,6 +39,8 @@
import org.codehaus.groovy.ast.expr.RangeExpression;
import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.Types;
import org.netbeans.editor.BaseDocument;
@@ -112,46 +115,86 @@
@Override
public void visitDeclarationExpression(DeclarationExpression expression) {
if (sameVariableName(leaf, expression.getLeftExpression())) {
- guessedType = deriveExpressonType(expression.getRightExpression());
+ ClassNode fromExpression = deriveExpressonType(expression.getRightExpression());
+ if (fromExpression != null) {
+ guessedType = fromExpression;
+ }
+ }
+ }
+
+ private ASTNode leafStatement;
+
+ /**
+ * After each statement certify that the leaf / completion point was not
+ * passed.
+ */
+ @Override
+ protected void visitStatement(Statement statement) {
+ super.visitStatement(statement);
+ if (statement == leafStatement) {
+ leafReached = true;
}
}
@Override
+ public void visitBlockStatement(BlockStatement statement) {
+ ASTNode prev = null;
+ for (Iterator<ASTNode> it = path.iterator(); it.hasNext(); ) {
+ ASTNode n = it.next();
+ if (n == statement) {
+ leafStatement = prev;
+ break;
+ }
+ prev = n;
+ }
+ super.visitBlockStatement(statement);
+ }
+
+ @Override
public void visitVariableExpression(VariableExpression expression) {
- if (expression.isSuperExpression()) {
- guessedType = expression.getType().getSuperClass();
- }
- if (null != expression.getAccessedVariable()) {
- Variable accessedVariable = expression.getAccessedVariable();
+ boolean guessed = true;
+ if (leaf instanceof VariableExpression && !sameVariableName(leaf, expression)) {
+ return;
+ }
+ if (expression.isSuperExpression()) {
+ guessedType = expression.getType().getSuperClass();
+ }
+ if (null != expression.getAccessedVariable()) {
+ Variable accessedVariable = expression.getAccessedVariable();
- if (accessedVariable.hasInitialExpression()) {
- Expression initialExpression = expression.getAccessedVariable().getInitialExpression();
- if (initialExpression instanceof ConstantExpression
- && !initialExpression.getText().equals("null")) { // NOI18N
- guessedType = ((ConstantExpression) initialExpression).getType();
- } else if (initialExpression instanceof ConstructorCallExpression) {
- guessedType = ClassHelper.make(((ConstructorCallExpression) initialExpression).getType().getName());
- } else if (initialExpression instanceof MethodCallExpression) {
- int newOffset = ASTUtils.getOffset(doc, initialExpression.getLineNumber(), initialExpression.getColumnNumber());
- AstPath newPath = new AstPath(path.root(), newOffset, doc);
- guessedType = MethodInference.findCallerType(initialExpression, newPath, doc, newOffset);
- } else if (initialExpression instanceof ListExpression) {
- guessedType = ((ListExpression) initialExpression).getType();
- } else if (initialExpression instanceof MapExpression) {
- guessedType = ((MapExpression) initialExpression).getType();
- } else if (initialExpression instanceof RangeExpression) {
- // this should work, but the type is Object - nut sure why
- // guessedType = ((RangeExpression)initialExpression).getType();
- guessedType = ClassHelper.makeWithoutCaching(Range.class, true);
- }
- } else if (accessedVariable instanceof Parameter) {
- Parameter param = (Parameter) accessedVariable;
- guessedType = param.getType();
+ if (accessedVariable.hasInitialExpression()) {
+ Expression initialExpression = expression.getAccessedVariable().getInitialExpression();
+ if (initialExpression instanceof ConstantExpression
+ && !initialExpression.getText().equals("null")) { // NOI18N
+ guessedType = ((ConstantExpression) initialExpression).getType();
+ } else if (initialExpression instanceof ConstructorCallExpression) {
+ guessedType = ClassHelper.make(((ConstructorCallExpression) initialExpression).getType().getName());
+ } else if (initialExpression instanceof MethodCallExpression) {
+ int newOffset = ASTUtils.getOffset(doc, initialExpression.getLineNumber(), initialExpression.getColumnNumber());
+ AstPath newPath = new AstPath(path.root(), newOffset, doc);
+ guessedType = MethodInference.findCallerType(initialExpression, newPath, doc, newOffset);
+ } else if (initialExpression instanceof ListExpression) {
+ guessedType = ((ListExpression) initialExpression).getType();
+ } else if (initialExpression instanceof MapExpression) {
+ guessedType = ((MapExpression) initialExpression).getType();
+ } else if (initialExpression instanceof RangeExpression) {
+ // this should work, but the type is Object - nut sure why
+ // guessedType = ((RangeExpression)initialExpression).getType();
+ guessedType = ClassHelper.makeWithoutCaching(Range.class, true);
+ } else {
+ guessed = false;
}
- } else if (!expression.getType().getName().equals("java.lang.Object")) {
- guessedType = expression.getType();
-
+ } else if (accessedVariable instanceof Parameter) {
+ Parameter param = (Parameter) accessedVariable;
+ guessedType = param.getType();
+ } else {
+ guessed = false;
}
+ }
+ if (!guessed && !expression.getType().getName().equals("java.lang.Object")) {
+ guessedType = expression.getType();
+
+ }
super.visitVariableExpression(expression);
}
@@ -172,6 +215,11 @@
guessedType = MethodInference.findCallerType(rightExpression, path, doc, cursorOffset);
} else if (rightExpression instanceof StaticMethodCallExpression) {
guessedType = MethodInference.findCallerType(rightExpression, path, doc, cursorOffset);
+ } else {
+ ClassNode cn = expression.getRightExpression().getType();
+ if (!cn.equals("java.lang.Object")) {
+ guessedType = cn;
+ }
}
}
}
diff --git a/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy b/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy
new file mode 100644
index 0000000..dad9bfb
--- /dev/null
+++ b/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy
@@ -0,0 +1,7 @@
+def reassignment() {
+ def varA = "ahoj"
+ def sub = varA.substring(0)
+
+ varA = ["a", "b"];
+ varA.lis
+}
diff --git a/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy.testReassignment_1.completion b/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy.testReassignment_1.completion
new file mode 100644
index 0000000..39ab57d
--- /dev/null
+++ b/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy.testReassignment_1.completion
@@ -0,0 +1,7 @@
+Code completion result for source line:
+def sub = varA.subs|tring(0)
+(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
+------------------------------------
+METHOD subSequence(int, int) [PUBLIC] CharSequence
+METHOD substring(int) [PUBLIC] String
+METHOD substring(int, int) [PUBLIC] String
diff --git a/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy.testReassignment_2.completion b/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy.testReassignment_2.completion
new file mode 100644
index 0000000..a9cb8a7
--- /dev/null
+++ b/groovy/groovy.editor/test/unit/data/testfiles/completion/flow/reassignment/Reassignment.groovy.testReassignment_2.completion
@@ -0,0 +1,6 @@
+Code completion result for source line:
+varA.lis|
+(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
+------------------------------------
+METHOD listIterator() [PUBLIC] ListIterator<E>
+METHOD listIterator(int) [PUBLIC] ListIterator<E>
diff --git a/groovy/groovy.editor/test/unit/data/testfiles/completion/method/methods4/Methods4.groovy b/groovy/groovy.editor/test/unit/data/testfiles/completion/method/methods4/Methods4.groovy
new file mode 100644
index 0000000..a682401
--- /dev/null
+++ b/groovy/groovy.editor/test/unit/data/testfiles/completion/method/methods4/Methods4.groovy
@@ -0,0 +1,21 @@
+class GroovyClass1 {
+ def method1() {}
+ def method2() {}
+ def method3() {}
+
+ interface ISuper {
+ def methodSuper();
+ }
+
+ interface I1 extends ISuper {
+ def methodA();
+ }
+}
+
+class GroovyClass2 {
+ def m2() {
+ GroovyClass1.I1 iface;
+ iface.meth
+
+ }
+}
diff --git a/groovy/groovy.editor/test/unit/data/testfiles/completion/method/methods4/Methods4.groovy.testMethods4.completion b/groovy/groovy.editor/test/unit/data/testfiles/completion/method/methods4/Methods4.groovy.testMethods4.completion
new file mode 100644
index 0000000..e8c482f
--- /dev/null
+++ b/groovy/groovy.editor/test/unit/data/testfiles/completion/method/methods4/Methods4.groovy.testMethods4.completion
@@ -0,0 +1,6 @@
+Code completion result for source line:
+iface.meth|
+(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
+------------------------------------
+METHOD methodA() [PUBLIC] Object
+METHOD methodSuper() [PUBLIC] Object
diff --git a/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/FlowCCTest.java b/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/FlowCCTest.java
index d87f2e3..31abe63 100644
--- a/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/FlowCCTest.java
+++ b/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/FlowCCTest.java
@@ -86,4 +86,12 @@
checkCompletion(BASE + "CollectionLiterals2.groovy", "map.ent^", false);
}
+ public void testReassignment_1() throws Exception {
+ checkCompletion(BASE + "Reassignment.groovy", "def sub = varA.subs^", false);
+ }
+
+ public void testReassignment_2() throws Exception {
+ checkCompletion(BASE + "Reassignment.groovy", "varA.lis^", false);
+ }
+
}
diff --git a/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/MethodCCTest.java b/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/MethodCCTest.java
index 02f1b2a..c3226af 100644
--- a/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/MethodCCTest.java
+++ b/groovy/groovy.editor/test/unit/src/org/netbeans/modules/groovy/editor/api/completion/MethodCCTest.java
@@ -149,5 +149,13 @@
public void testCompletionNoPrefixString2() throws Exception {
checkCompletion(BASE + "CompletionNoPrefixString2.groovy", "def name='Petr'.^", false);
}
+
+ /**
+ * Checks that the completion contains methods from inner interfaces and their
+ * superinterfaces.
+ */
+ public void testMethods4() throws Exception {
+ checkCompletion(BASE + "Methods4.groovy", "iface.meth^", false);
+ }
}
diff --git a/ide/extexecution/apichanges.xml b/ide/extexecution/apichanges.xml
index 5ff14c9..3801d44 100644
--- a/ide/extexecution/apichanges.xml
+++ b/ide/extexecution/apichanges.xml
@@ -91,7 +91,23 @@
<!-- ACTUAL CHANGES BEGIN HERE: -->
<changes>
-
+ <change>
+ <api name="extexecution_api"/>
+ <summary>StartupExtender may return unescaped parameters</summary>
+ <version major="1" minor="62"/>
+ <date day="10" month="8" year="2021"/>
+ <author login="sdedic"/>
+ <compatibility addition="yes"/>
+ <description>
+ The <a href="@TOP@/org/netbeans/spi/extexecution/startup/StartupExtenderImplementation.html">StartupExtenderImplementation</a>
+ javadoc did not specify how to handle parameters with spaces in them. Some of the implementations quote/escape the parameters they
+ return, but most of them not. This causes issues later when the parameters are processed or re-arranged into the final
+ commandline. This change allows a <a href="@TOP@/org/netbeans/spi/extexecution/startup/StartupExtenderImplementation.html">StartupExtenderImplementation</a>
+ to declare its quoting policy.
+ </description>
+ <class package="org.netbeans.spi.extexecution.startup" name="StartupExtenderImplementation"/>
+ <class package="org.netbeans.api.extexecution.startup" name="StartupExtender"/>
+ </change>
<change>
<api name="extexecution_api"/>
<summary>postExecution callback with exit code value</summary>
diff --git a/ide/extexecution/src/org/netbeans/api/extexecution/startup/StartupExtender.java b/ide/extexecution/src/org/netbeans/api/extexecution/startup/StartupExtender.java
index 24a2f6c..8256479 100644
--- a/ide/extexecution/src/org/netbeans/api/extexecution/startup/StartupExtender.java
+++ b/ide/extexecution/src/org/netbeans/api/extexecution/startup/StartupExtender.java
@@ -23,8 +23,10 @@
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.extexecution.startup.StartupExtenderRegistrationOptions;
import org.netbeans.modules.extexecution.startup.StartupExtenderRegistrationProcessor;
import org.netbeans.spi.extexecution.startup.StartupExtenderImplementation;
+import org.openide.util.BaseUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.Parameters;
@@ -45,10 +47,13 @@
private final String description;
private final List<String> arguments;
+
+ private final List<String> rawArguments;
- private StartupExtender(String description, List<String> arguments) {
+ private StartupExtender(String description, List<String> arguments, List<String> rawArguments) {
this.description = description;
this.arguments = arguments;
+ this.rawArguments = rawArguments;
}
/**
@@ -81,8 +86,30 @@
List<StartupExtender> res = new ArrayList<StartupExtender>();
for (Lookup.Item<StartupExtenderImplementation> item : lkp.lookupResult(StartupExtenderImplementation.class).allItems()) {
- StartupExtender extender = new StartupExtender(item.getDisplayName(),
- item.getInstance().getArguments(context, mode));
+ StartupExtenderImplementation impl = item.getInstance();
+ List<String> args = impl.getArguments(context, mode);
+ List<String> rawArgs;
+
+ if (!(impl instanceof StartupExtenderRegistrationOptions) ||
+ ((StartupExtenderRegistrationOptions)impl).argumentsQuoted()) {
+ rawArgs = new ArrayList<>(args.size());
+ for (String s : args) {
+ String[] parsed = BaseUtilities.parseParameters(s);
+ rawArgs.add(String.join(" ", parsed));
+ }
+ } else {
+ rawArgs = args;
+ List<String> quotedArgs = new ArrayList<>();
+ for (String s : args) {
+ if (s.isEmpty()) {
+ quotedArgs.add(s);
+ } else {
+ quotedArgs.add(BaseUtilities.escapeParameters(new String[] { s }));
+ }
+ }
+ args = quotedArgs;
+ }
+ StartupExtender extender = new StartupExtender(item.getDisplayName(), args, rawArgs);
LOG.log(Level.FINE, " {0} => {1}", new Object[] {extender.description, extender.getArguments()});
res.add(extender);
}
@@ -108,6 +135,19 @@
public List<String> getArguments() {
return arguments;
}
+
+ /**
+ * List of arguments. Items of the list are literal values that should
+ * be used by the process, without escaping. They can contain spaces, and any
+ * quote, doublequote or backslashes in their literal meaning. It is up to the
+ * caller to appropriately quote or escape the values.
+ *
+ * @return list of arguments.
+ * @since 1.62
+ */
+ public List<String> getRawArguments() {
+ return rawArguments;
+ }
/**
* Class representing the startup mode of the process.
diff --git a/ide/extexecution/src/org/netbeans/modules/extexecution/startup/ProxyStartupExtender.java b/ide/extexecution/src/org/netbeans/modules/extexecution/startup/ProxyStartupExtender.java
index 101660f..e246456 100644
--- a/ide/extexecution/src/org/netbeans/modules/extexecution/startup/ProxyStartupExtender.java
+++ b/ide/extexecution/src/org/netbeans/modules/extexecution/startup/ProxyStartupExtender.java
@@ -80,4 +80,22 @@
return delegate;
}
}
+
+ /**
+ * Returns false only if the extender registration explicitly says it does not escape arguments.
+ */
+ public boolean argumentsQuoted() {
+ Object o = attributes.get(StartupExtenderRegistrationProcessor.QUOTED_ATTRIBUTE);
+ // older binaries do not contain the attribute, so fall back to 'escaped' mode.
+ return o == null || o != Boolean.FALSE;
+ }
+
+ /**
+ * Enhanced version that declares escaping policy from 1.62
+ */
+ public static class V2 extends ProxyStartupExtender implements StartupExtenderRegistrationOptions {
+ public V2(Map<String, ?> attributes) {
+ super(attributes);
+ }
+ }
}
diff --git a/ide/extexecution/src/org/netbeans/modules/extexecution/startup/StartupExtenderRegistrationOptions.java b/ide/extexecution/src/org/netbeans/modules/extexecution/startup/StartupExtenderRegistrationOptions.java
new file mode 100644
index 0000000..29aeb05
--- /dev/null
+++ b/ide/extexecution/src/org/netbeans/modules/extexecution/startup/StartupExtenderRegistrationOptions.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.extexecution.startup;
+
+/**
+ * Interface internal to the module connecting {@link StartupExtender} registrations
+ * and API.
+ * @author sdedic
+ */
+public interface StartupExtenderRegistrationOptions {
+ public boolean argumentsQuoted();
+}
diff --git a/ide/extexecution/src/org/netbeans/modules/extexecution/startup/StartupExtenderRegistrationProcessor.java b/ide/extexecution/src/org/netbeans/modules/extexecution/startup/StartupExtenderRegistrationProcessor.java
index 52906fd..87f495f 100644
--- a/ide/extexecution/src/org/netbeans/modules/extexecution/startup/StartupExtenderRegistrationProcessor.java
+++ b/ide/extexecution/src/org/netbeans/modules/extexecution/startup/StartupExtenderRegistrationProcessor.java
@@ -44,6 +44,8 @@
public static final String DELEGATE_ATTRIBUTE = "delegate"; // NOI18N
public static final String START_MODE_ATTRIBUTE = "startMode"; // NOI18N
+
+ public static final String QUOTED_ATTRIBUTE = "argumentsQuoted"; // NOI18N
@Override
protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws LayerGenerationException {
@@ -68,8 +70,9 @@
File f = layer(element).instanceFile(PATH, null)
.instanceAttribute(DELEGATE_ATTRIBUTE, StartupExtenderImplementation.class, annotation, null)
.stringvalue(START_MODE_ATTRIBUTE, builder.toString())
+ .boolvalue(QUOTED_ATTRIBUTE, annotation.argumentsQuoted())
.bundlevalue("displayName", element.getAnnotation(StartupExtenderImplementation.Registration.class).displayName()) // NOI18N
- .methodvalue("instanceCreate", "org.netbeans.spi.extexecution.startup.StartupExtender", "createProxy") // NOI18N
+ .methodvalue("instanceCreate", "org.netbeans.spi.extexecution.startup.StartupExtender", "createProxy2") // NOI18N
.position(element.getAnnotation(StartupExtenderImplementation.Registration.class).position()); // NOI18N
f.write();
}
diff --git a/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtender.java b/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtender.java
index 372f1e4..719aa39 100644
--- a/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtender.java
+++ b/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtender.java
@@ -27,10 +27,22 @@
*/
final class StartupExtender {
+ /**
+ * Legacy layer factory that is still used by binaries compiled against < 1.62
+ * @param map
+ * @return
+ */
static StartupExtenderImplementation createProxy(Map<String,?> map) {
return new ProxyStartupExtender(map);
}
+ /**
+ * New layer factory, allows to declare quoting/escaping policy
+ */
+ static StartupExtenderImplementation createProxy2(Map<String,?> map) {
+ return new ProxyStartupExtender.V2(map);
+ }
+
private StartupExtender() {}
}
diff --git a/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtenderImplementation.java b/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtenderImplementation.java
index fcfb231..fb79af0 100644
--- a/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtenderImplementation.java
+++ b/ide/extexecution/src/org/netbeans/spi/extexecution/startup/StartupExtenderImplementation.java
@@ -32,7 +32,12 @@
* startup. Typically the server plugin implementor or project will query
* the arguments via API counterpart {@link StartupExtender}. Of course it is
* not mandatory to use such arguments and there is no way to force it.
- *
+ * <p>
+ * The implementation <b>should not quote or escape parameters</b> it returns. Each item in the
+ * {@link #getArguments(org.openide.util.Lookup, org.netbeans.api.extexecution.startup.StartupExtender.StartMode) returned list}
+ * should be passed as it should be seen by the target process and the API user (launcher) decides on quoting appropriate for the
+ * intended purpose (i.e. to construct a command line, depending on OS).
+ *
* @author Petr Hejl
* @since 1.30
* @see StartupExtender
@@ -82,5 +87,15 @@
*/
int position() default Integer.MAX_VALUE;
+ /**
+ * Value {@code false} means the extender leaves escaping or quoting arguments
+ * to the user who constructs the commandline or processes the arguments. To
+ * preserve backwards compatibility, the default value is {@code true}.
+ * <p>
+ * Implementors are <b>strongly encouraged</b> to declare escaping as false.
+ * @return false, if the arguments are not escaped. True otherwise.
+ * @since 1.62
+ */
+ boolean argumentsQuoted() default true;
}
}
diff --git a/ide/extexecution/test/unit/src/META-INF/MANIFEST.MF b/ide/extexecution/test/unit/src/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a010841
--- /dev/null
+++ b/ide/extexecution/test/unit/src/META-INF/MANIFEST.MF
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.modules.extexecution.xtest/1
+OpenIDE-Module-Specification-Version: 1.0
+OpenIDE-Module-Module-Dependencies: org.netbeans.modules.extexecution/2 > 1.62
+OpenIDE-Module-Short-Description: Tests for ExternalExecution API
+OpenIDE-Module-Layer: org/netbeans/api/extexecution/resources/mf-layer.xml
+OpenIDE-Module-Name: External Execution API tests
+OpenIDE-Module-Public-Packages: -
diff --git a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/resources/mf-layer.xml b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/resources/mf-layer.xml
new file mode 100644
index 0000000..ccb043b
--- /dev/null
+++ b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/resources/mf-layer.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN"
+ "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem>
+ <folder name="StartupExtender">
+ <!-- This registration was generated by the @StartupExtenderImplementation.Registration before
+ 1.62. Different instance was created -->
+ <file name="org-netbeans-api-extexecution-startup-LegacyStartupExtender2.instance">
+ <!--org.netbeans.api.extexecution.startup.LegacyStartupExtender-->
+ <attr name="delegate" newvalue="org.netbeans.api.extexecution.startup.LegacyStartupExtender2"/>
+ <attr name="startMode" stringvalue="PROFILE"/>
+ <attr name="displayName" stringvalue="Test Legacy"/>
+ <attr
+ methodvalue="org.netbeans.spi.extexecution.startup.StartupExtender.createProxy" name="instanceCreate"/>
+ <attr intvalue="1500" name="position"/>
+ </file>
+ </folder>
+</filesystem>
diff --git a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/LegacyStartupExtender.java b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/LegacyStartupExtender.java
new file mode 100644
index 0000000..ee9fe34
--- /dev/null
+++ b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/LegacyStartupExtender.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.api.extexecution.startup;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.spi.extexecution.startup.StartupExtenderImplementation;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author sdedic
+ */
+@StartupExtenderImplementation.Registration(displayName="Test Legacy", startMode=StartupExtender.StartMode.PROFILE, position = 1000)
+public class LegacyStartupExtender implements StartupExtenderImplementation {
+ public static boolean enable = false;
+
+ @Override
+ public List<String> getArguments(Lookup context, StartupExtender.StartMode mode) {
+ if (!enable) {
+ return Collections.emptyList();
+ } else {
+ return Arrays.asList("\"Quoted parameter\"", "Normal-parameter");
+ }
+ }
+}
diff --git a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/LegacyStartupExtender2.java b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/LegacyStartupExtender2.java
new file mode 100644
index 0000000..9a3574f
--- /dev/null
+++ b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/LegacyStartupExtender2.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.api.extexecution.startup;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.spi.extexecution.startup.StartupExtenderImplementation;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author sdedic
+ */
+public class LegacyStartupExtender2 implements StartupExtenderImplementation {
+ public static boolean enable = false;
+
+ @Override
+ public List<String> getArguments(Lookup context, StartupExtender.StartMode mode) {
+ if (!enable) {
+ return Collections.emptyList();
+ } else {
+ return Arrays.asList("\"Quoted parameter l\"", "Normal-parameter-l");
+ }
+ }
+}
diff --git a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/StartupExtenderTest.java b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/StartupExtenderTest.java
index 72d0887..8a8526c 100644
--- a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/StartupExtenderTest.java
+++ b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/StartupExtenderTest.java
@@ -18,6 +18,8 @@
*/
package org.netbeans.api.extexecution.startup;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.extexecution.startup.ProxyStartupExtender;
@@ -36,6 +38,13 @@
super(name);
}
+ @Override
+ protected void tearDown() throws Exception {
+ LegacyStartupExtender.enable = false;
+ LegacyStartupExtender2.enable = false;
+ V2StartupExtender.enable = false;
+ }
+
public void testLaziness() {
Lookup lookup = Lookups.forPath(StartupExtenderRegistrationProcessor.PATH);
assertTrue(lookup.lookup(StartupExtenderImplementation.class) instanceof ProxyStartupExtender);
@@ -46,12 +55,12 @@
List<StartupExtender> argsDebug =
StartupExtender.getExtenders(context, StartupExtender.StartMode.DEBUG);
- assertEquals(1, argsDebug.size());
+ assertEquals(4, argsDebug.size());
assertTrue(argsDebug.get(0).getArguments().isEmpty());
List<StartupExtender> argsNormal =
StartupExtender.getExtenders(context, StartupExtender.StartMode.NORMAL);
- assertEquals(1, argsNormal.size());
+ assertEquals(4, argsNormal.size());
StartupExtender args = argsNormal.get(0);
assertEquals("Test", args.getDescription());
@@ -60,4 +69,56 @@
assertEquals("arg1", args.getArguments().get(0));
assertEquals("arg2", args.getArguments().get(1));
}
+
+ /**
+ * Checks that legacy extender's output is properly unquoted.
+ */
+ public void testRawArguments() {
+ LegacyStartupExtender.enable = true;
+ LegacyStartupExtender2.enable = true;
+ V2StartupExtender.enable = true;
+
+ List<StartupExtender> argsProfile = StartupExtender.getExtenders(Lookup.EMPTY, StartupExtender.StartMode.PROFILE);
+ assertEquals(4, argsProfile.size());
+ List<String> args = new ArrayList<>();
+ List<String> rawArgs = new ArrayList<>();
+
+ for (StartupExtender e : argsProfile) {
+ rawArgs.addAll(e.getRawArguments());
+ args.addAll(e.getArguments());
+ }
+
+ // raw arguments do not contain quoting even for extenders that supply quoted args
+ assertEquals(Arrays.asList(
+ "Quoted parameter", "Normal-parameter",
+ "Quoted parameter l", "Normal-parameter-l",
+ "Quoted parameter V2", "Normal-parameter-v2"
+ ), rawArgs);
+ }
+
+ /**
+ * Checks that the new extender's output is quoted for backwards compatibility
+ */
+ public void testQuotedArguments() {
+ LegacyStartupExtender.enable = true;
+ LegacyStartupExtender2.enable = true;
+ V2StartupExtender.enable = true;
+
+ List<StartupExtender> argsProfile = StartupExtender.getExtenders(Lookup.EMPTY, StartupExtender.StartMode.PROFILE);
+ assertEquals(4, argsProfile.size());
+ List<String> args = new ArrayList<>();
+ List<String> rawArgs = new ArrayList<>();
+
+ for (StartupExtender e : argsProfile) {
+ rawArgs.addAll(e.getRawArguments());
+ args.addAll(e.getArguments());
+ }
+
+ assertEquals(Arrays.asList(
+ "\"Quoted parameter\"", "Normal-parameter",
+ "\"Quoted parameter l\"", "Normal-parameter-l",
+ "\"Quoted parameter V2\"", "Normal-parameter-v2"
+ ), args);
+
+ }
}
diff --git a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/TestStartupExtender.java b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/TestStartupExtender.java
index e41a4d2..2e69afd 100644
--- a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/TestStartupExtender.java
+++ b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/TestStartupExtender.java
@@ -28,7 +28,7 @@
*
* @author Petr Hejl
*/
-@StartupExtenderImplementation.Registration(displayName="Test", startMode=StartMode.NORMAL)
+@StartupExtenderImplementation.Registration(displayName="Test", startMode=StartMode.NORMAL, position = 0)
public class TestStartupExtender implements StartupExtenderImplementation {
@Override
diff --git a/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/V2StartupExtender.java b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/V2StartupExtender.java
new file mode 100644
index 0000000..cff94d7
--- /dev/null
+++ b/ide/extexecution/test/unit/src/org/netbeans/api/extexecution/startup/V2StartupExtender.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.api.extexecution.startup;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.spi.extexecution.startup.StartupExtenderImplementation;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author sdedic
+ */
+@StartupExtenderImplementation.Registration(displayName="Test V2",
+ startMode=StartupExtender.StartMode.PROFILE, argumentsQuoted = false, position = 2000)
+public class V2StartupExtender implements StartupExtenderImplementation {
+ public static boolean enable = false;
+
+ @Override
+ public List<String> getArguments(Lookup context, StartupExtender.StartMode mode) {
+ if (!enable) {
+ return Collections.emptyList();
+ } else {
+ return Arrays.asList("Quoted parameter V2", "Normal-parameter-v2");
+ }
+ }
+}
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/HtmlJavaPagesNodeFactory.java b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/HtmlJavaPagesNodeFactory.java
new file mode 100644
index 0000000..a139619
--- /dev/null
+++ b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/HtmlJavaPagesNodeFactory.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.gradle.htmlui;
+
+import java.awt.Image;
+import org.netbeans.modules.gradle.api.NbGradleProject;
+import org.netbeans.modules.gradle.spi.nodes.AbstractGradleNodeList;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collections;
+import java.util.List;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.ui.support.NodeFactory;
+import org.netbeans.spi.project.ui.support.NodeList;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataFolder;
+import org.openide.nodes.FilterNode;
+import org.openide.nodes.Node;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
+
+@NbBundle.Messages({
+ "MSG_HtmlJavaPages=Frontend UI Pages"
+})
+@NodeFactory.Registration(projectType = NbGradleProject.GRADLE_PROJECT_TYPE, position = 77)
+public final class HtmlJavaPagesNodeFactory implements NodeFactory {
+
+ @Override
+ public NodeList<?> createNodes(Project p) {
+ return new HtmlJavaPagesList(p);
+ }
+
+ private static class HtmlJavaPagesList extends AbstractGradleNodeList<FileObject> implements PropertyChangeListener {
+
+ final Project project;
+
+ HtmlJavaPagesList(Project project) {
+ this.project = project;
+ }
+
+ @Override
+ public List<FileObject> keys() {
+ FileObject pages = project.getProjectDirectory().getFileObject("src/main/webapp/pages"); // NOI18N
+ return pages != null ? Collections.singletonList(pages) : Collections.<FileObject>emptyList();
+ }
+
+ @Override
+ public Node node(FileObject key) {
+ DataFolder df = DataFolder.findFolder(key);
+ FilterNode fn = new FilterNode(df.getNodeDelegate().cloneNode()) {
+ @Override
+ public Image getIcon(int type) {
+ return ImageUtilities.loadImage("org/netbeans/modules/gradle/htmlui/DukeHTML.png"); // NOI18N
+ }
+
+ @Override
+ public Image getOpenedIcon(int type) {
+ return getIcon(type);
+ }
+
+ @Override
+ public String getName() {
+ return "pages"; // NOI18N
+ }
+
+ @Override
+ public String getDisplayName() {
+ return Bundle.MSG_HtmlJavaPages();
+ }
+ };
+ return fn;
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) {
+ fireChange();
+ }
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener list) {
+ NbGradleProject.removePropertyChangeListener(project, this);
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener list) {
+ NbGradleProject.addPropertyChangeListener(project, this);
+ }
+
+ }
+}
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/desktop_build.gradle.fmk b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/desktop_build.gradle.fmk
index f29b5f6..71b86b0 100644
--- a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/desktop_build.gradle.fmk
+++ b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/desktop_build.gradle.fmk
@@ -51,8 +51,8 @@
</#noparse>
dependencies {
implementation commonProject
- implementation "org.netbeans.html:net.java.html.boot:1.6.1"
- implementation "com.dukescript.api:javafx.beaninfo:0.5"
+ implementation "org.netbeans.html:net.java.html.boot:1.7.2"
+ implementation "com.dukescript.api:javafx.beaninfo:0.6"
runtimeOnly "com.dukescript.api:javafx.base:8.60.11"
- runtimeOnly "org.netbeans.html:net.java.html.boot.fx:1.6.1"
+ runtimeOnly "org.netbeans.html:net.java.html.boot.fx:1.7.2"
}
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/gradle-wrapper.properties.fmk b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/gradle-wrapper.properties.fmk
deleted file mode 100644
index 46ca126..0000000
--- a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/gradle-wrapper.properties.fmk
+++ /dev/null
@@ -1,25 +0,0 @@
-<#--
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-
--->
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/gradle.properties.fmk b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/gradle.properties.fmk
index b5379c3..ebe4ca9 100644
--- a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/gradle.properties.fmk
+++ b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/gradle.properties.fmk
@@ -18,9 +18,9 @@
under the License.
-->
-action.run.args=bck2brwsrShow
+action.run.args=bck2brwsrShow -t
action.debug.args=run --debug-jvm
action.custom-1=Run in Browser
-action.custom-1.args=bck2brwsrShow
+action.custom-1.args=bck2brwsrShow -t
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/layer.xml b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/layer.xml
index cbc65ca..2345148 100644
--- a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/layer.xml
+++ b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/layer.xml
@@ -44,13 +44,6 @@
<file name="settings.gradle" url="settings.gradle.fmk">
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
</file>
- <folder name="gradle">
- <folder name="wrapper">
- <file name="gradle-wrapper.properties" url="gradle-wrapper.properties.fmk">
- <attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
- </file>
- </folder>
- </folder>
<folder name="app">
<file name="build.gradle" url="app_build.gradle.fmk">
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
@@ -110,6 +103,7 @@
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
</file>
<file name="index.html" url="src_main_webapp_pages_index.html.fmk">
+ <attr name="important" boolvalue="true"/>
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
</file>
</folder>
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/root_build.gradle.fmk b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/root_build.gradle.fmk
index eda3807..2ba3db0 100644
--- a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/root_build.gradle.fmk
+++ b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/root_build.gradle.fmk
@@ -18,15 +18,14 @@
under the License.
-->
-<#noparse>
-plugins {
- id "me.tatarka.retrolambda" version "3.7.1"
-}
-
apply plugin: 'java'
-
-group 'com.dukescript.demo'
-version '1.0-SNAPSHOT'
+<#if group?has_content>
+group '${group}'
+</#if>
+<#if version?has_content>
+version '${version}'
+</#if>
+<#noparse>
allprojects {
repositories {
@@ -38,9 +37,10 @@
sourceCompatibility = '1.8'
dependencies {
- implementation "org.netbeans.html:net.java.html.json:1.6.1"
+ implementation "org.netbeans.html:net.java.html.json:1.7.2"
implementation "com.dukescript.api:javafx.base:8.60.11"
- implementation "com.dukescript.api:javafx.beaninfo:0.5"
- runtimeOnly "org.netbeans.html:ko4j:1.6.1"
+ implementation "com.dukescript.api:javafx.beaninfo:0.6"
+ annotationProcessor "com.dukescript.api:javafx.beaninfo:0.6"
+ runtimeOnly "org.netbeans.html:ko4j:1.7.2"
}
</#noparse>
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/src_main_java_Demo.fmk b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/src_main_java_Demo.fmk
index dea0ca2..5d96631 100644
--- a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/src_main_java_Demo.fmk
+++ b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/src_main_java_Demo.fmk
@@ -30,31 +30,20 @@
import javafx.collections.FXCollections;
import static net.java.html.json.Models.applyBindings;
-public final class Demo implements FXBeanInfo.Provider {
- private final StringProperty desc = new SimpleStringProperty(this, "desc", "Buy Milk");
- private final ListProperty<String> todos = new SimpleListProperty<>(this, "todos", FXCollections.observableArrayList());
- private final IntegerBinding numTodos = Bindings.createIntegerBinding(todos::size, todos);
+@FXBeanInfo.Generate
+public final class Demo extends DemoBeanInfo {
+ final StringProperty desc = new SimpleStringProperty(this, "desc", "");
+ final ListProperty<String> todos = new SimpleListProperty<>(this, "todos", FXCollections.observableArrayList());
+ final IntegerBinding numTodos = Bindings.createIntegerBinding(todos::size, todos);
void addTodo() {
todos.getValue().add(desc.getValue());
desc.setValue("");
}
- private final FXBeanInfo info = FXBeanInfo.newBuilder(this)
- .property(desc)
- .property(todos)
- .property("numTodos", numTodos)
- .action("addTodo", this::addTodo)
- .build();
-
- @Override
- public FXBeanInfo getFXBeanInfo() {
- return info;
- }
-
public static void onPageLoad() {
Demo model = new Demo();
+ model.desc.setValue("Try Java in browser @ " + System.currentTimeMillis());
applyBindings(model);
}
-
}
\ No newline at end of file
diff --git a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/web_build.gradle.fmk b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/web_build.gradle.fmk
index e1dca2d..43ee3ab 100644
--- a/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/web_build.gradle.fmk
+++ b/java/gradle.htmlui/src/org/netbeans/modules/gradle/htmlui/resources/web_build.gradle.fmk
@@ -19,13 +19,11 @@
-->
buildscript {
- ext.bck2brwsr_version = '0.31'
-
repositories {
mavenCentral()
}
dependencies {
- classpath "org.apidesign.bck2brwsr:bck2brwsr-maven-plugin:$bck2brwsr_version"
+ classpath "org.apidesign.bck2brwsr:bck2brwsr-maven-plugin:0.51"
}
}
@@ -47,11 +45,6 @@
runtimeOnly "com.dukescript.api:javafx.base:8.60.11"
}
-configurations.bck2brwsr {
- exclude group: 'org.jetbrains', module: 'annotations'
- extendsFrom configurations.runtimeClasspath
-}
-
bck2brwsrPages.from {
fileTree("${commonProject.projectDir}/src/main/webapp/pages")
}
diff --git a/java/gradle.htmlui/test/unit/src/org/netbeans/modules/gradle/htmlui/CreateArchetypeTest.java b/java/gradle.htmlui/test/unit/src/org/netbeans/modules/gradle/htmlui/CreateArchetypeTest.java
index 65a1c6d..87433d3 100644
--- a/java/gradle.htmlui/test/unit/src/org/netbeans/modules/gradle/htmlui/CreateArchetypeTest.java
+++ b/java/gradle.htmlui/test/unit/src/org/netbeans/modules/gradle/htmlui/CreateArchetypeTest.java
@@ -36,10 +36,13 @@
import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.gradle.spi.actions.AfterBuildActionHook;
import org.netbeans.modules.gradle.spi.newproject.TemplateOperation;
+import org.netbeans.spi.project.ActionProgress;
import org.netbeans.spi.project.ActionProvider;
+import org.netbeans.spi.project.ui.LogicalViewProvider;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.LocalFileSystem;
+import org.openide.nodes.Node;
import org.openide.util.lookup.Lookups;
public class CreateArchetypeTest extends NbTestCase {
@@ -118,6 +121,7 @@
assertTrue(Arrays.asList(actions.getSupportedActions()).contains(ActionProvider.COMMAND_BUILD));
actions.isActionEnabled(ActionProvider.COMMAND_BUILD, mainPrj.getLookup());
+ assertLogicalView(mainPrj);
invokeCommand(actions, ActionProvider.COMMAND_BUILD, mainPrj);
assertFile("JAR created", dest, "build", "libs", "dest-1.0-SNAPSHOT.jar");
@@ -139,13 +143,41 @@
assertFile("Main script created", dest, "web", "build", "web", "bck2brwsr.js");
}
+ private void assertLogicalView(Project mainPrj) {
+ LogicalViewProvider lvp = mainPrj.getLookup().lookup(LogicalViewProvider.class);
+ assertNotNull("Logical view found", lvp);
+ Node logicalView = lvp.createLogicalView();
+ final Node[] children = logicalView.getChildren().getNodes(true);
+ for (Node ch : children) {
+ if (ch.getName().equals("pages") && "Frontend UI Pages".equals(ch.getDisplayName())) {
+ FileObject pages = ch.getLookup().lookup(FileObject.class);
+ assertNotNull("Pages node provides FileObject: " + ch, pages);
+ assertNotNull("There is index.html", pages.getFileObject("index.html"));
+ return;
+ }
+ }
+ fail("Cannot find Frontend Pages in " + Arrays.toString(children));
+ }
+
protected void invokeCommand(ActionProvider actions, String cmd, Project prj) throws IllegalArgumentException, InterruptedException {
CountDownLatch waiter = new CountDownLatch(1);
- AfterBuildActionHook notifier = (action, context, res, out) -> {
- waiter.countDown();
+ boolean[] status = { false, false };
+ ActionProgress ap = new ActionProgress() {
+ @Override
+ protected void started() {
+ status[0] = true;
+ }
+
+ @Override
+ public void finished(boolean success) {
+ status[1] = success;
+ waiter.countDown();
+ }
};
- actions.invokeAction(cmd, Lookups.fixed(prj, notifier));
+ actions.invokeAction(cmd, Lookups.fixed(prj, ap));
+ assertTrue("ActionProgress was started", status[0]);
waiter.await();
+ assertTrue("ActionProgress was successfully finished", status[1]);
}
private AssertContent assertFile(String msg, FileObject root, String... path) throws IOException {
diff --git a/java/gradle.java/nbproject/project.xml b/java/gradle.java/nbproject/project.xml
index 3ef753b..b8ba6b9 100644
--- a/java/gradle.java/nbproject/project.xml
+++ b/java/gradle.java/nbproject/project.xml
@@ -101,7 +101,7 @@
<compile-dependency/>
<run-dependency>
<release-version>2</release-version>
- <specification-version>1.41.1</specification-version>
+ <specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/execute/JavaExecTokenProvider.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/execute/JavaExecTokenProvider.java
index a54c8ec..f477056 100644
--- a/java/gradle.java/src/org/netbeans/modules/gradle/java/execute/JavaExecTokenProvider.java
+++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/execute/JavaExecTokenProvider.java
@@ -136,7 +136,7 @@
List<String> extraArgs = new ArrayList<>();
if (mode != null) {
for (StartupExtender group : StartupExtender.getExtenders(new AbstractLookup(ic), mode)) {
- extraArgs.addAll(group.getArguments());
+ extraArgs.addAll(group.getRawArguments());
}
}
diff --git a/java/java.disco/src/org/netbeans/modules/java/disco/BrowsePanel.java b/java/java.disco/src/org/netbeans/modules/java/disco/BrowsePanel.java
index 744dff4..fa69532 100644
--- a/java/java.disco/src/org/netbeans/modules/java/disco/BrowsePanel.java
+++ b/java/java.disco/src/org/netbeans/modules/java/disco/BrowsePanel.java
@@ -19,26 +19,28 @@
package org.netbeans.modules.java.disco;
import static org.netbeans.modules.java.disco.SwingWorker2.submit;
+
import java.io.File;
import javax.swing.JFileChooser;
import org.checkerframework.checker.guieffect.qual.UIEffect;
import org.checkerframework.checker.nullness.qual.NonNull;
+import org.openide.util.NbBundle;
+@NbBundle.Messages({
+ "DiscoBrowsePanel.searching=Searching...",
+ "DiscoBrowsePanel.error=Requested JDK not found."
+})
public class BrowsePanel extends javax.swing.JPanel {
+ private final BrowseWizardPanel panel;
private final WizardState state;
private final Client discoClient;
- @UIEffect
- public static BrowsePanel create(WizardState state) {
- BrowsePanel d = new BrowsePanel(state);
- d.init();
- return d;
- }
-
- public BrowsePanel(WizardState state) {
+ public BrowsePanel(BrowseWizardPanel panel, WizardState state) {
+ this.panel = panel;
this.state = state;
this.discoClient = Client.getInstance();
+ init();
}
@UIEffect
@@ -53,21 +55,26 @@
public void addNotify() {
super.addNotify();
//we do this every time
- jdkDescription.setText(state.selection.getFileName());
if (state.selection.get(null) == null) {
+ jdkDescription.setText(Bundle.DiscoBrowsePanel_searching());
//OK, we have a quick selection so the file name was not the best, let's try to load it
submit(() -> {
return state.selection.get(discoClient);
}).then(pkg -> {
//re-set the name
jdkDescription.setText(state.selection.getFileName());
-
- }).execute(); //NOTE: ignoring errors on purpose...
+ panel.fireChangeListeners();
+ }).handle(ex -> {
+ jdkDescription.setText(Bundle.DiscoBrowsePanel_error());
+ }).execute();
+ } else {
+ jdkDescription.setText(state.selection.getFileName());
}
}
public boolean isOK() {
- return !downloadPathText.getText().isEmpty();
+ return state.selection.get(null) != null
+ && !downloadPathText.getText().isEmpty();
}
@NonNull
diff --git a/java/java.disco/src/org/netbeans/modules/java/disco/BrowseWizardPanel.java b/java/java.disco/src/org/netbeans/modules/java/disco/BrowseWizardPanel.java
index 2a080e0..cf4abb4 100644
--- a/java/java.disco/src/org/netbeans/modules/java/disco/BrowseWizardPanel.java
+++ b/java/java.disco/src/org/netbeans/modules/java/disco/BrowseWizardPanel.java
@@ -30,7 +30,7 @@
@Override
protected BrowsePanel createComponent() {
- return BrowsePanel.create(state);
+ return new BrowsePanel(this, state);
}
@Override
diff --git a/java/java.disco/src/org/netbeans/modules/java/disco/FoojayPlatformInstall.java b/java/java.disco/src/org/netbeans/modules/java/disco/FoojayPlatformInstall.java
index 070caf9..8270c9f 100644
--- a/java/java.disco/src/org/netbeans/modules/java/disco/FoojayPlatformInstall.java
+++ b/java/java.disco/src/org/netbeans/modules/java/disco/FoojayPlatformInstall.java
@@ -24,7 +24,7 @@
import org.openide.util.NbBundle;
@NbBundle.Messages({
- "DiscoPlatformInstall.displayName=Download OpenJDK (via foojay Disco API)"
+ "DiscoPlatformInstall.displayName=Download OpenJDK (via Foojay.io Disco API)"
})
public class FoojayPlatformInstall extends CustomPlatformInstall {
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbProtocolServer.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbProtocolServer.java
index 5f14324..5f9581b 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbProtocolServer.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbProtocolServer.java
@@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
@@ -88,6 +89,7 @@
import org.netbeans.modules.nativeimage.api.debug.NIVariable;
import org.netbeans.spi.debugger.ui.DebuggingView.DVFrame;
import org.netbeans.spi.debugger.ui.DebuggingView.DVThread;
+import org.openide.util.RequestProcessor;
/**
*
@@ -101,6 +103,7 @@
private final NbDisconnectRequestHandler disconnectRequestHandler = new NbDisconnectRequestHandler();
private final NbBreakpointsRequestHandler breakpointsRequestHandler = new NbBreakpointsRequestHandler();
private final NbVariablesRequestHandler variablesRequestHandler = new NbVariablesRequestHandler();
+ private final RequestProcessor evaluationRP = new RequestProcessor(NbProtocolServer.class.getName(), 3);
private boolean initialized = false;
private Future<Void> runningServer;
@@ -458,7 +461,7 @@
evaluateNative(niDebugger, expression, threadId, response);
}
return response;
- });
+ }, evaluationRP);
}
private void evaluateJPDA(JPDADebugger debugger, String expression, int threadId, EvaluateResponse response) {
@@ -487,7 +490,7 @@
} catch (InvalidExpressionException ex) {
toString = variable.getValue();
}
- response.setResult(toString);
+ response.setResult(Objects.toString(toString));
response.setVariablesReference(referenceId);
response.setType(variable.getType());
response.setIndexedVariables(Math.max(indexedVariables, 0));
diff --git a/java/java.source.ant/nbproject/project.xml b/java/java.source.ant/nbproject/project.xml
index ad46ca5..94db0b6 100644
--- a/java/java.source.ant/nbproject/project.xml
+++ b/java/java.source.ant/nbproject/project.xml
@@ -226,6 +226,11 @@
<test/>
</test-dependency>
<test-dependency>
+ <code-name-base>org.netbeans.modules.java.source.base</code-name-base>
+ <compile-dependency/>
+ <test/>
+ </test-dependency>
+ <test-dependency>
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
<recursive/>
<compile-dependency/>
diff --git a/java/java.source.ant/test/unit/src/org/netbeans/modules/java/source/ant/ProjectRunnerImplTest.java b/java/java.source.ant/test/unit/src/org/netbeans/modules/java/source/ant/ProjectRunnerImplTest.java
index e80b70d..3810016 100644
--- a/java/java.source.ant/test/unit/src/org/netbeans/modules/java/source/ant/ProjectRunnerImplTest.java
+++ b/java/java.source.ant/test/unit/src/org/netbeans/modules/java/source/ant/ProjectRunnerImplTest.java
@@ -53,6 +53,8 @@
import org.netbeans.api.java.project.runner.JavaRunner;
import org.netbeans.junit.MockServices;
import org.netbeans.spi.extexecution.startup.StartupExtenderImplementation;
+import org.netbeans.spi.queries.FileEncodingQueryImplementation;
+import org.openide.util.lookup.ServiceProvider;
/**
*
@@ -259,4 +261,11 @@
}
}
+
+ @ServiceProvider(service=FileEncodingQueryImplementation.class)
+ public static final class FEQImpl extends FileEncodingQueryImplementation {
+ @Override public Charset getEncoding(FileObject file) {
+ return Charset.forName("UTF-8");
+ }
+ }
}
diff --git a/java/java.testrunner.ui/src/org/netbeans/modules/java/testrunner/ui/ComputeTestMethodsImpl.java b/java/java.testrunner.ui/src/org/netbeans/modules/java/testrunner/ui/ComputeTestMethodsImpl.java
index 4b2bd43..6236049 100644
--- a/java/java.testrunner.ui/src/org/netbeans/modules/java/testrunner/ui/ComputeTestMethodsImpl.java
+++ b/java/java.testrunner.ui/src/org/netbeans/modules/java/testrunner/ui/ComputeTestMethodsImpl.java
@@ -36,6 +36,7 @@
import org.netbeans.modules.parsing.spi.TaskIndexingMode;
import org.openide.filesystems.FileObject;
import org.openide.util.Lookup;
+import org.openide.util.RequestProcessor;
import org.openide.util.lookup.ServiceProvider;
/**
@@ -45,6 +46,8 @@
@ServiceProvider(service=JavaSourceTaskFactory.class)
public class ComputeTestMethodsImpl extends EditorAwareJavaSourceTaskFactory {
+ private static final RequestProcessor WORKER = new RequestProcessor(ComputeTestMethodsImpl.class.getName(), 1, false, false);
+
public ComputeTestMethodsImpl() {
super(Phase.ELEMENTS_RESOLVED, Priority.NORMAL, TaskIndexingMode.ALLOWED_DURING_SCAN);
}
@@ -100,7 +103,7 @@
}
if (!cancel.get()) {
- TestMethodController.setTestMethods(doc, methods);
+ WORKER.post(() -> TestMethodController.setTestMethods(doc, methods));
}
}
}
diff --git a/java/jshell.support/nbproject/project.xml b/java/jshell.support/nbproject/project.xml
index 0905707..41709af 100644
--- a/java/jshell.support/nbproject/project.xml
+++ b/java/jshell.support/nbproject/project.xml
@@ -245,7 +245,7 @@
<compile-dependency/>
<run-dependency>
<release-version>2</release-version>
- <specification-version>1.48</specification-version>
+ <specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
diff --git a/java/jshell.support/src/org/netbeans/modules/jshell/j2se/JShellStartupExtender.java b/java/jshell.support/src/org/netbeans/modules/jshell/j2se/JShellStartupExtender.java
index 0117231..2589ba9 100644
--- a/java/jshell.support/src/org/netbeans/modules/jshell/j2se/JShellStartupExtender.java
+++ b/java/jshell.support/src/org/netbeans/modules/jshell/j2se/JShellStartupExtender.java
@@ -40,10 +40,8 @@
*
* @author sdedic
*/
-@StartupExtenderImplementation.Registration(displayName = "Java Shell", position = 10000, startMode = {
- StartMode.DEBUG,
- StartMode.NORMAL,
-})
+@StartupExtenderImplementation.Registration(displayName = "Java Shell", position = 10000, argumentsQuoted = false,
+ startMode = { StartMode.DEBUG, StartMode.NORMAL })
public class JShellStartupExtender implements StartupExtenderImplementation {
private static final Logger LOG = Logger.getLogger(JShellStartupExtender.class.getName());
@@ -77,9 +75,7 @@
J2SEPropertyEvaluator prjEval = p.getLookup().lookup(J2SEPropertyEvaluator.class);
JavaPlatform platform = ShellProjectUtils.findPlatform(p);
- List<String> args = ShellProjectUtils.quoteCmdArgs(
- ShellLaunchManager.buildLocalJVMAgentArgs(platform, agent, prjEval.evaluator()::getProperty)
- );
+ List<String> args = ShellLaunchManager.buildLocalJVMAgentArgs(platform, agent, prjEval.evaluator()::getProperty);
args.addAll(ShellProjectUtils.launchVMOptions(p));
diff --git a/java/maven/nbproject/project.xml b/java/maven/nbproject/project.xml
index 0dfb9ca..9d105e2 100644
--- a/java/maven/nbproject/project.xml
+++ b/java/maven/nbproject/project.xml
@@ -131,7 +131,7 @@
<compile-dependency/>
<run-dependency>
<release-version>2</release-version>
- <specification-version>1.30</specification-version>
+ <specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
diff --git a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
index 4f07e4c..d303f7f 100644
--- a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
+++ b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
@@ -118,7 +118,7 @@
* The example will <b>append</b> <code>-DvmArg2=2</code> to VM arguments and <b>replaces</b> all user
* program arguments with <code>"paramY"</code>. Append mode can be controlled using {@link ExplicitProcessParameters.Builder#appendArgs} or
* {@link ExplicitProcessParameters.Builder#appendPriorityArgs}.
- *
+ *
* @author Milos Kleint (mkleint@codehaus.org)
* @author Svata Dedic (svatopluk.dedic@gmail.com)
*/
@@ -128,18 +128,18 @@
static final String ENV_JAVAHOME = "Env.JAVA_HOME"; //NOI18N
private static final String KEY_UUID = "NB_EXEC_MAVEN_PROCESS_UUID"; //NOI18N
-
+
private static final String NETBEANS_MAVEN_COMMAND_LINE = "NETBEANS_MAVEN_COMMAND_LINE"; //NOI18N
-
+
private Process process;
private String processUUID;
private Process preProcess;
private String preProcessUUID;
private static final SpecificationVersion VER17 = new SpecificationVersion("1.7"); //NOI18N
private static final Logger LOGGER = Logger.getLogger(MavenCommandLineExecutor.class.getName());
-
+
private static final RequestProcessor RP = new RequestProcessor(MavenCommandLineExecutor.class.getName(),1);
-
+
private final static RequestProcessor UPDATE_INDEX_RP = new RequestProcessor(RunUtils.class.getName(), 5);
/**
* Execute maven build in NetBeans execution engine.
@@ -158,7 +158,7 @@
}
return runner.execute(config, io, tc);
}
-
+
/**
* Hooks for tests to mock the Maven execution.
*/
@@ -192,12 +192,12 @@
return task;
}
}
-
+
public MavenCommandLineExecutor(RunConfig conf, InputOutput io, TabContext tc) {
super(conf, tc);
this.io = io;
}
-
+
/**
* not to be called directly.. use execute();
*/
@@ -222,7 +222,7 @@
}
int executionresult = -10;
final InputOutput ioput = getInputOutput();
-
+
final ProgressHandle handle = ProgressHandle.createHandle(clonedConfig.getTaskDisplayName(), this, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -246,7 +246,7 @@
}
if (clonedConfig.getPreExecution() != null) {
if (!elem.checkRunConfig(clonedConfig.getPreExecution(), exCon)) {
- //#238360 when the check says don't execute, we still need to close the output and mark it for reuse
+ //#238360 when the check says don't execute, we still need to close the output and mark it for reuse
ioput.getOut().close();
ioput.getErr().close();
actionStatesAtFinish(null, null);
@@ -257,9 +257,8 @@
}
}
}
-
+
// final Properties originalProperties = clonedConfig.getProperties();
-
handle.start();
processInitialMessage();
boolean isMaven3 = !isMaven2();
@@ -272,7 +271,6 @@
}
}
-
CommandLineOutputHandler out = new CommandLineOutputHandler(ioput, clonedConfig.getProject(), handle, clonedConfig, isMaven3 && singlethreaded);
try {
BuildExecutionSupport.registerRunningItem(item);
@@ -352,7 +350,7 @@
return true;
}
}
-
+
/**
* Overridable by tests.
*/
@@ -371,7 +369,7 @@
env.put(KEY_UUID, uuid);
Processes.killTree(prcs, env);
}
-
+
@Override
public boolean cancel() {
final Process pre = preProcess;
@@ -391,7 +389,7 @@
});
return true;
}
-
+
private static List<String> createMavenExecutionCommand(RunConfig config, Constructor base) {
List<String> toRet = new ArrayList<String>(base.construct());
@@ -415,8 +413,7 @@
String quote = "\"";
// the command line parameters with space in them need to be quoted and escaped to arrive
// correctly to the java runtime on windows
- String escaped = "\\" + quote;
- for (Map.Entry<? extends String,? extends String> entry : config.getProperties().entrySet()) {
+ for (Map.Entry<? extends String, ? extends String> entry : config.getProperties().entrySet()) {
String k = entry.getKey();
// filter out env vars AND internal properties.
if (k.startsWith(ENV_PREFIX) || k.startsWith(INTERNAL_PREFIX)) {
@@ -424,15 +421,12 @@
}
//skip envs, these get filled in later.
//#228901 since u21 we need to use cmd /c to execute on windows, quotes get escaped and when there is space in value, the value gets wrapped in quotes.
- String value = (Utilities.isWindows() ? entry.getValue().replace(quote, escaped) : entry.getValue().replace(quote, "'"));
- if (Utilities.isWindows() && value.endsWith("\"")) {
- //#201132 property cannot end with 2 double quotes, add a space to the end after our quote to prevent the state
- value = value + " ";
- }
- String s = "-D" + entry.getKey() + "=" + (Utilities.isWindows() && value.contains(" ") ? quote + value + quote : value);
+ String value = quote2apos(entry.getValue());
+ String p = "-D" + entry.getKey() + "=" + value;
+ String s = (Utilities.isWindows() && value.contains(" ") ? quote + p + quote : p);
toRet.add(s);
}
-
+
//TODO based on a property? or UI option? can this backfire?
//#224526
//execute in encoding that is based on project.build.sourceEncoding to have the output of exec:exec, surefire:test and others properly encoded.
@@ -449,7 +443,7 @@
if (!config.isInteractive()) {
toRet.add("--batch-mode"); //NOI18N
}
-
+
if (!config.isRecursive()) {
toRet.add("--non-recursive");//NOI18N
}
@@ -509,7 +503,7 @@
}
String profiles = "";//NOI18N
-
+
for (Object profile : config.getActivatedProfiles()) {
profiles = profiles + "," + profile;//NOI18N
}
@@ -517,13 +511,59 @@
profiles = profiles.substring(1);
toRet.add("-P" + profiles);//NOI18N
}
-
+
for (String goal : config.getGoals()) {
toRet.add(goal);
}
-
+
return toRet;
}
+
+ /**
+ * Quotes the parameter string using apostrohphes. As Maven does not understand \' escape in quoted string, work around by terminating single-quote
+ * and pass the apostrophe as double-quoted single-character string, then open single-quote again.
+ * @param s
+ * @return quoted string
+ */
+ private static String quote2apos(String s) {
+ boolean inQuote = false;
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\') {
+ i++;
+ if (i < s.length()) {
+ char c2 = s.charAt(i);
+ if (inQuote) {
+ if (c2 == '\'') {
+ sb.append("'\"'\"'");
+ continue;
+ } else if (c2 == '\"') {
+ sb.append(c2);
+ continue;
+ }
+ }
+ sb.append(c);
+ sb.append(c2);
+ } else {
+ sb.append(c);
+ }
+ } else if (c == '\'') {
+ if (inQuote) {
+ sb.append("'\"'\"'");
+ } else {
+ inQuote = !inQuote;
+ sb.append('\'');
+ }
+ } else if (c == '"') {
+ inQuote = !inQuote;
+ sb.append('\'');
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
private ProcessBuilder constructBuilder(final RunConfig clonedConfig, InputOutput ioput) {
File javaHome = null;
@@ -588,12 +628,12 @@
Constructor constructeur = new ShellConstructor(mavenHome);
List<String> cmdLine = createMavenExecutionCommand(clonedConfig, constructeur);
-
+
//#228901 on windows, since u21 we must use cmd /c
// the working format is ""C:\Users\mkleint\space in path\apache-maven-3.0.4\bin\mvn.bat"
- //-Dexec.executable=java -Dexec.args="-jar
- //C:\Users\mkleint\Documents\NetBeansProjects\JavaApplication13\dist\JavaApplication13.jar
- //-Dxx=\"space path\" -Dfoo=bar" exec:exec""
+ //-Dexec.executable=java -Dexec.args="-jar
+ //C:\Users\mkleint\Documents\NetBeansProjects\JavaApplication13\dist\JavaApplication13.jar
+ //-Dxx=\"space path\" -Dfoo=bar" exec:exec""
if (cmdLine.get(0).equals("cmd")) {
//merge all items after cmd /c into one string and quote it.
StringBuilder sb = new StringBuilder();
@@ -602,12 +642,12 @@
it.next(); //cmd
it.next(); //c
String m = it.next();
-
+
sb.append(m);
while (it.hasNext()) {
sb.append(" ").append(it.next());
}
-
+
// NETBEANS-3251, NETBEANS-3254:
// JDK-8221858 (non public) / CVE-2019-2958 changed the way cmd
// command lines are verified and made it "difficult" to have embedded
@@ -636,11 +676,11 @@
// TODO: do we really put *all* the env vars there? maybe filter, M2_HOME and JDK_HOME?
builder.environment().put(env, val);
if (!env.equals(CosChecker.NETBEANS_PROJECT_MAPPINGS)
- && !env.equals(NETBEANS_MAVEN_COMMAND_LINE)) { //don't show to user
+ && !env.equals(NETBEANS_MAVEN_COMMAND_LINE)) { //don't show to user
display.append(Utilities.escapeParameters(new String[] {env + "=" + val})).append(' '); // NOI18N
}
}
-
+
if (mavenHome != null) {
//#195039
builder.environment().put("M2_HOME", mavenHome.getAbsolutePath());
@@ -665,9 +705,9 @@
}
display.append(Utilities.escapeParameters(command.toArray(new String[command.size()])));
}
-
+
printGray(ioput, display.toString());
-
+
return builder;
}
@@ -727,14 +767,14 @@
if (isMaven2()) {
printGray(ioput, "WARNING: Using Maven 2.x for execution, NetBeans cannot establish links between current project and output directories of dependency projects with Compile on Save turned on. Only works with Maven 3.0+.");
}
-
+
}
if (clonedConfig.getProperties().containsKey(ModelRunConfig.EXEC_MERGED)) {
printGray(ioput, "\nDefault '" + clonedConfig.getActionName() + "' action exec.args merged with maven-exec-plugin arguments declared in pom.xml.");
}
-
+
}
-
+
boolean isMaven2() {
File mvnHome = EmbedderFactory.getEffectiveMavenHome();
String version = MavenSettings.getCommandLineMavenVersion(mvnHome);
@@ -774,7 +814,7 @@
}
}
return list.contains("-T") || list.contains("--threads");
- }
+ }
private File guessBestMaven(RunConfig clonedConfig, InputOutput ioput) {
MavenProject mp = clonedConfig.getMavenProject();
@@ -861,8 +901,8 @@
if (ver == null) {
return null;
}
-
- File f = getAltMavenLocation();
+
+ File f = getAltMavenLocation();
File child = FileUtil.normalizeFile(new File(f, "apache-maven-" + ver));
if (child.exists()) {
return child;
@@ -874,7 +914,7 @@
//this url pattern works for all versions except the last one 3.2.3
//which is only under <mirror>/apache/maven/maven-3/3.2.3/binaries/
URL[] urls = new URL[] {new URL("http://archive.apache.org/dist/maven/binaries/apache-maven-" + ver + "-bin.zip"),
- new URL("http://archive.apache.org/dist/maven/maven-3/" + ver + "/binaries/apache-maven-" + ver + "-bin.zip")};
+ new URL("http://archive.apache.org/dist/maven/maven-3/" + ver + "/binaries/apache-maven-" + ver + "-bin.zip")};
InputStream is = null;
for (URL u : urls) {
try {
diff --git a/java/maven/src/org/netbeans/modules/maven/runjar/LaunchArgPrereqsChecker.java b/java/maven/src/org/netbeans/modules/maven/runjar/LaunchArgPrereqsChecker.java
index 1c2924c..a5438e0 100644
--- a/java/maven/src/org/netbeans/modules/maven/runjar/LaunchArgPrereqsChecker.java
+++ b/java/maven/src/org/netbeans/modules/maven/runjar/LaunchArgPrereqsChecker.java
@@ -86,7 +86,7 @@
}
}
for (StartupExtender group : StartupExtender.getExtenders(new AbstractLookup(ic), mode)) {
- fixedArgs.addAll(group.getArguments());
+ fixedArgs.addAll(group.getRawArguments());
}
}
diff --git a/java/maven/src/org/netbeans/modules/maven/runjar/MavenExecuteUtils.java b/java/maven/src/org/netbeans/modules/maven/runjar/MavenExecuteUtils.java
index 614f4e8..4367fa4 100644
--- a/java/maven/src/org/netbeans/modules/maven/runjar/MavenExecuteUtils.java
+++ b/java/maven/src/org/netbeans/modules/maven/runjar/MavenExecuteUtils.java
@@ -550,34 +550,33 @@
return c == '\'' || c == '"';
}
- public static String joinParameters(List<String> params) {
- StringBuilder sb = new StringBuilder();
+ public static List<String> escapeParameters(List<String> params) {
+ List<String> ret = new ArrayList<>();
for (String s : params) {
if (s == null) {
continue;
}
- if (sb.length() > 0) {
- sb.append(" ");
- }
if (s.length() > 1) {
char c = s.charAt(0);
if (isQuoteChar(c) && s.charAt(s.length() - 1) == c) {
- sb.append(s);
+ ret.add(s);
continue;
}
}
// note: does not care about escaped spaces.
if (!s.contains(" ")) {
- sb.append(s.replace("'", "\\'").replace("\"", "\\\""));
+ ret.add(s.replace("'", "\\'").replace("\"", "\\\""));
} else {
- sb.append("\"").append(
- s.replace("\"", "\\\"")
- ).append("\"");
+ ret.add("\"" + s.replace("\"", "\\\"") + "\"");
}
}
- return sb.toString();
+ return ret;
}
+ public static String joinParameters(List<String> params) {
+ return String.join(" ", escapeParameters(params));
+ }
+
public static List<String> extractDebugJVMOptions(String argLine) {
Iterable<String> split = propertySplitter(argLine, true);
List<String> toRet = new ArrayList<String>();
diff --git a/java/maven/src/org/netbeans/modules/maven/runjar/PropertySplitter.java b/java/maven/src/org/netbeans/modules/maven/runjar/PropertySplitter.java
index 8880da1..bfae302 100644
--- a/java/maven/src/org/netbeans/modules/maven/runjar/PropertySplitter.java
+++ b/java/maven/src/org/netbeans/modules/maven/runjar/PropertySplitter.java
@@ -85,7 +85,7 @@
buffer.append(escape).append(c);
}
escapeNext = false;
- } else if (!inQuote && c == escape) {
+ } else if (c == escape) {
escapeNext = true;
} else if (inQuote) {
if (c == quoteChar) {
diff --git a/java/maven/src/org/netbeans/modules/maven/runjar/RunJarStartupArgs.java b/java/maven/src/org/netbeans/modules/maven/runjar/RunJarStartupArgs.java
index 3f32b56..811c713 100644
--- a/java/maven/src/org/netbeans/modules/maven/runjar/RunJarStartupArgs.java
+++ b/java/maven/src/org/netbeans/modules/maven/runjar/RunJarStartupArgs.java
@@ -39,7 +39,6 @@
import org.netbeans.modules.maven.execute.ModelRunConfig;
import org.netbeans.spi.project.ActionProvider;
import org.netbeans.spi.project.ProjectServiceProvider;
-import org.openide.util.Lookup;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
@@ -108,7 +107,7 @@
}
}
for (StartupExtender group : StartupExtender.getExtenders(new AbstractLookup(ic), mode)) {
- fixedArgs.addAll(group.getArguments());
+ fixedArgs.addAll(group.getRawArguments());
}
}
diff --git a/java/maven/test/unit/data/exec/PrintCommandLine.java b/java/maven/test/unit/data/exec/PrintCommandLine.java
new file mode 100644
index 0000000..fec95bd
--- /dev/null
+++ b/java/maven/test/unit/data/exec/PrintCommandLine.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package test;
+
+public class PrintCommandLine {
+ public static void main(String[] args) {
+ System.err.println("::PrintCommandLineStart");
+ System.err.print("argCount="); System.err.println(args.length);
+
+ int index = 1;
+ for (String s : args) {
+ System.err.print("appArg." + index + "="); System.err.println(s);
+ index++;
+ }
+
+ for (String k : System.getProperties().stringPropertyNames()) {
+ if (k.startsWith("test.")) {
+ System.err.print(k + "="); System.err.println(System.getProperty(k));
+ }
+ }
+ System.err.println("::PrintCommandLineEnd");
+ }
+}
diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/runjar/RunJarStartupArgsTest.java b/java/maven/test/unit/src/org/netbeans/modules/maven/runjar/RunJarStartupArgsTest.java
new file mode 100644
index 0000000..5d8914f
--- /dev/null
+++ b/java/maven/test/unit/src/org/netbeans/modules/maven/runjar/RunJarStartupArgsTest.java
@@ -0,0 +1,303 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.maven.runjar;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import org.junit.Assume;
+import org.netbeans.api.extexecution.startup.StartupExtender;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.maven.NbMavenProjectImpl;
+import org.netbeans.modules.maven.api.execute.RunConfig;
+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.extexecution.startup.StartupExtenderImplementation;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.execution.ExecutorTask;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.test.TestFileUtils;
+import org.openide.util.BaseUtilities;
+import org.openide.util.Lookup;
+import org.openide.windows.InputOutput;
+import org.openide.windows.OutputListener;
+import org.openide.windows.OutputWriter;
+
+/**
+ *
+ * @author sdedic
+ */
+public class RunJarStartupArgsTest extends NbTestCase {
+
+ public RunJarStartupArgsTest(String name) {
+ super(name);
+ }
+
+ private FileObject d;
+
+ protected @Override void setUp() throws Exception {
+ clearWorkDir();
+ d = FileUtil.toFileObject(getWorkDir());
+ }
+
+
+ @Override
+ protected void tearDown() throws Exception {
+ LegacyStartupExtenderImpl.enabled = false;
+ CurrentStartupExtenderImpl.enabled = false;
+ super.tearDown();
+ }
+
+ /**
+ * Legacy Extenders give quoted arguments to preserve spaces. The quoted strings
+ * must be properly incorporated in exec.vmArgs property.
+ * @throws Exception
+ */
+ public void testLegacyExtenderWithSpaces() throws Exception {
+ Assume.assumeFalse(BaseUtilities.isWindows());
+ LegacyStartupExtenderImpl.enabled = true;
+ Properties p = doTestSpacedExtender();
+ assertEquals("/tmp/spaced folder/", p.getProperty("test.spaced.folder.path"));
+ assertEquals("/tmp/another space/", p.getProperty("test.another.space"));
+ }
+
+ /**
+ * Checks that 'modern' StartupExtender that declares it does NOT escape arguments work.
+ * @throws Exception
+ */
+ public void testNetBeans12_4Extender() throws Exception {
+ Assume.assumeFalse(BaseUtilities.isWindows());
+ CurrentStartupExtenderImpl.enabled = true;
+ Properties p = doTestSpacedExtender();
+ assertEquals("/tmp/spaced folder/", p.getProperty("test.spaced.folder.path"));
+ assertEquals("/tmp/another space/", p.getProperty("test.another.space"));
+ }
+
+ private Properties doTestSpacedExtender() throws Exception {
+ System.setProperty("netbeans.dirs", System.getProperty("cluster.path.final", ""));
+ TestFileUtils.writeFile(d, "pom.xml",
+ "<project>\n" +
+ " <modelVersion>4.0.0</modelVersion>\n" +
+ " <groupId>testgrp</groupId>\n" +
+ " <artifactId>testart</artifactId>\n" +
+ " <version>1.0</version>\n" +
+ " <properties>\n" +
+ " <project.mainclass>test.PrintCommandLine</project.mainclass>\n" +
+ " <exec.java.bin>${java.home}/bin/java</exec.java.bin>\n" +
+ " </properties>\n" +
+ "</project>\n");
+
+ FileObject f = FileUtil.createFolder(d, "src/main/java/test");
+ FileObject source = FileUtil.toFileObject(getDataDir()).getFileObject("exec/PrintCommandLine.java");
+ FileObject result = FileUtil.copyFile(source, f, source.getName());
+ System.err.println("Testing application: " + result.getPath());
+
+ Project proj = ProjectManager.getDefault().findProject(d);
+ RunConfig rc = ActionToGoalUtils.createRunConfig(ActionProvider.COMMAND_RUN, proj.getLookup().lookup(NbMavenProjectImpl.class), proj.getLookup());
+ rc.setProperty("packageClassName", "test.PrintCommandLine");
+ ((BeanRunConfig)rc).setShowDebug(true);
+ ((BeanRunConfig)rc).setShowError(true);
+
+ class CaptureOutput implements InputOutput {
+
+ class OW extends OutputWriter {
+ public OW(Writer w) {
+ super(w);
+ }
+
+ @Override
+ public void println(String s, OutputListener l) throws IOException {
+ super.println(s);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ }
+ }
+
+ StringWriter sw = new StringWriter();
+
+ OW writer = new OW(sw);
+
+ @Override
+ public OutputWriter getOut() {
+ return writer;
+ }
+
+ @Override
+ public Reader getIn() {
+ return InputOutput.NULL.getIn();
+ }
+
+ @Override
+ public OutputWriter getErr() {
+ return InputOutput.NULL.getErr();
+ }
+
+ @Override
+ public void closeInputOutput() {
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+
+ @Override
+ public void setOutputVisible(boolean value) {
+ }
+
+ @Override
+ public void setErrVisible(boolean value) {
+ }
+
+ @Override
+ public void setInputVisible(boolean value) {
+ }
+
+ @Override
+ public void select() {
+ }
+
+ @Override
+ public boolean isErrSeparated() {
+ return true;
+ }
+
+ @Override
+ public void setErrSeparated(boolean value) {
+ }
+
+ @Override
+ public boolean isFocusTaken() {
+ return false;
+ }
+
+ @Override
+ public void setFocusTaken(boolean value) {
+ }
+
+ @Override
+ public Reader flushReader() {
+ return getIn();
+ }
+
+ }
+
+ final CaptureOutput out = new CaptureOutput();
+
+ ExecutorTask t = new ExecutorTask(() -> {
+ }) {
+ @Override
+ public void stop() {
+ }
+
+ @Override
+ public int result() {
+ return 0;
+ }
+
+ @Override
+ public InputOutput getInputOutput() {
+ return out;
+ }
+ };
+
+ MavenCommandLineExecutor cme = new MavenCommandLineExecutor(rc, out, null);
+
+ cme.setTask(t);
+ cme.run();
+
+ out.writer.flush();
+
+ String[] lines = out.sw.toString().split("\n");
+ int from = 0;
+ for (; from < lines.length; from++) {
+ if (lines[from].startsWith("::PrintCommandLineStart")) {
+ from++;
+ break;
+ }
+ }
+ assertTrue(from > 0);
+
+ Properties p = new Properties();
+ while (from < lines.length) {
+ String s = lines[from];
+ if (s.startsWith("::PrintCommandLineEnd")) {
+ break;
+ }
+ int eq = s.indexOf('=');
+ p.put(s.substring(0, eq), s.substring(eq + 1));
+ from++;
+ }
+
+ return p;
+ }
+
+ /**
+ * Returns a quoted string with spaces, to observe that a legacy behaviour works. This is used by e.g. profiler, which
+ * quotes its data path or path to JNI libraries (NB may be installed with a folder-with-spaces).
+ */
+ @StartupExtenderImplementation.Registration(displayName = "Test legacy", startMode = { StartupExtender.StartMode.NORMAL })
+ public static class LegacyStartupExtenderImpl implements StartupExtenderImplementation {
+ static boolean enabled = false;
+
+ @Override
+ public List<String> getArguments(Lookup context, StartupExtender.StartMode mode) {
+ if (!enabled) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(
+ "-Dtest.spaced.folder.path=\"/tmp/spaced folder/\"",
+ "-Dtest.another.space=\"/tmp/another space/\""
+ );
+ }
+
+ }
+
+ /**
+ * Returns a quoted string with spaces, to observe that a legacy behaviour works. This is used by e.g. profiler, which
+ * quotes its data path or path to JNI libraries (NB may be installed with a folder-with-spaces).
+ */
+ @StartupExtenderImplementation.Registration(displayName = "Test 12.4", startMode = { StartupExtender.StartMode.NORMAL }, argumentsQuoted = false)
+ public static class CurrentStartupExtenderImpl implements StartupExtenderImplementation {
+ static boolean enabled = false;
+
+ @Override
+ public List<String> getArguments(Lookup context, StartupExtender.StartMode mode) {
+ if (!enabled) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(
+ "-Dtest.spaced.folder.path=/tmp/spaced folder/",
+ "-Dtest.another.space=/tmp/another space/"
+ );
+ }
+
+ }
+}
diff --git a/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/ApiGenAnnotationsProvider.java b/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/ApiGenAnnotationsProvider.java
index 71c22ee..1992134 100644
--- a/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/ApiGenAnnotationsProvider.java
+++ b/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/ApiGenAnnotationsProvider.java
@@ -86,6 +86,7 @@
new FilesourceTag(),
new GlobalTag(),
new IgnoreTag(),
+ new InheritDocTag(),
new InternalTag(),
new LicenseTag(),
new LinkTag(),
@@ -116,6 +117,7 @@
new ExampleTag(),
new GlobalTag(),
new IgnoreTag(),
+ new InheritDocTag(),
new InternalTag(),
new LicenseTag(),
new LinkTag(),
@@ -143,6 +145,7 @@
new FinalTag(),
new GlobalTag(),
new IgnoreTag(),
+ new InheritDocTag(),
new InternalTag(),
new LicenseTag(),
new LinkTag(),
diff --git a/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/Bundle.properties b/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/Bundle.properties
index a0dcc36..37cae40 100644
--- a/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/Bundle.properties
+++ b/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/Bundle.properties
@@ -500,6 +500,32 @@
}\n\
</code></pre>
+InheritDocTag.documentation=<p style="font-weight: bold; font-size: 1.2em">inline {@inheritDoc}</p>\
+<p>\
+This inline tag is used to inherit a description from a parent class into child classes.\
+</p>\
+<p>\
+<code>{@inheritDoc}</code>\
+</p>\
+<p style="font-weight: bold; font-size: 1.1em">Example</p>\
+<pre><code>\n\
+/**\n\
+\ * Parent title.\n\
+\ *\n\
+\ * Parent Description.\n\
+\ */\n\
+class ParentClass\n\
+{\n\
+}\n\
+\n\
+/**\n\
+\ * {@inheritdoc}\n\
+\ */\n\
+class ChildClass extends ParentClass\n\
+{\n\
+}\n\
+</code></pre>
+
InternalTag.documentation=<p style="font-weight: bold; font-size: 1.2em">@internal</p>\
<p>\
Mark documentation as private, internal to the software project.\
@@ -1443,4 +1469,4 @@
class Blah {\n\
\ ...\n\
}\n\
-</code></pre>
\ No newline at end of file
+</code></pre>
diff --git a/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/InheritDocTag.java b/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/InheritDocTag.java
new file mode 100644
index 0000000..f982bab
--- /dev/null
+++ b/php/php.apigen/src/org/netbeans/modules/php/apigen/annotations/InheritDocTag.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.php.apigen.annotations;
+
+import org.netbeans.modules.php.spi.annotation.AnnotationCompletionTag;
+import org.openide.util.NbBundle;
+
+/**
+ * inline {@code {@inheritDoc}} tag.
+ */
+public class InheritDocTag extends AnnotationCompletionTag {
+
+ public InheritDocTag() {
+ super("inheritDoc", "@inheritDoc", // NOI18N
+ NbBundle.getMessage(UsesTag.class, "InheritDocTag.documentation")); // NOI18N
+ }
+
+}
diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.form b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.form
index 6584c64..9f64be0 100644
--- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.form
+++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.form
@@ -51,7 +51,6 @@
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="noteLabel" alignment="0" min="-2" max="-2" attributes="0"/>
- <Component id="informationLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="learnMoreLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="emptyLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
@@ -94,9 +93,7 @@
<Component id="debuggerPortOptionLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="optionsLabel" min="-2" max="-2" attributes="0"/>
- <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
- <Component id="informationLabel" min="-2" max="-2" attributes="0"/>
- <EmptySpace max="-2" attributes="0"/>
+ <EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="learnMoreLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="emptyLabel" min="-2" max="-2" attributes="0"/>
@@ -135,15 +132,6 @@
<EventHandler event="mouseEntered" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="optionsLabelMouseEntered"/>
</Events>
</Component>
- <Component class="javax.swing.JLabel" name="informationLabel">
- <Properties>
- <Property name="text" type="java.lang.String" value="<html><a href="#">More information about Xdebug2 installation/configuration</a>"/>
- </Properties>
- <Events>
- <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="informationLabelMousePressed"/>
- <EventHandler event="mouseEntered" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="informationLabelMouseEntered"/>
- </Events>
- </Component>
<Component class="javax.swing.JLabel" name="learnMoreLabel">
<Properties>
<Property name="text" type="java.lang.String" value="<html><a href="#">Learn more about Xdebug</a>"/>
diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.java
index b10630c..204bc8c 100644
--- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.java
+++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ConnectionErrMessage.java
@@ -113,7 +113,6 @@
noteLabel = new JLabel();
debuggerPortOptionLabel = new JLabel();
optionsLabel = new JLabel();
- informationLabel = new JLabel();
learnMoreLabel = new JLabel();
emptyLabel = new JLabel();
copySettingsLabel = new JLabel();
@@ -136,16 +135,6 @@
}
});
- informationLabel.setText("<html><a href=\"#\">More information about Xdebug2 installation/configuration</a>");
- informationLabel.addMouseListener(new MouseAdapter() {
- public void mousePressed(MouseEvent evt) {
- informationLabelMousePressed(evt);
- }
- public void mouseEntered(MouseEvent evt) {
- informationLabelMouseEntered(evt);
- }
- });
-
learnMoreLabel.setText("<html><a href=\"#\">Learn more about Xdebug</a>");
learnMoreLabel.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
@@ -186,7 +175,6 @@
.addContainerGap()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(noteLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
- .addComponent(informationLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(learnMoreLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(emptyLabel)
.addGroup(layout.createSequentialGroup()
@@ -219,9 +207,7 @@
.addComponent(debuggerPortOptionLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(optionsLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(informationLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addGap(18, 18, 18)
.addComponent(learnMoreLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(emptyLabel)
@@ -242,14 +228,6 @@
showUrl("https://xdebug.org/docs"); // NOI18N
}//GEN-LAST:event_learnMoreLabelMousePressed
- private void informationLabelMouseEntered(MouseEvent evt) {//GEN-FIRST:event_informationLabelMouseEntered
- setHandCursor(evt);
- }//GEN-LAST:event_informationLabelMouseEntered
-
- private void informationLabelMousePressed(MouseEvent evt) {//GEN-FIRST:event_informationLabelMousePressed
- showUrl("http://wiki.netbeans.org/HowToConfigureXDebug"); // NOI18N
- }//GEN-LAST:event_informationLabelMousePressed
-
private void optionsLabelMouseEntered(MouseEvent evt) {//GEN-FIRST:event_optionsLabelMouseEntered
setHandCursor(evt);
}//GEN-LAST:event_optionsLabelMouseEntered
@@ -322,7 +300,6 @@
private JButton copySettingsXdebug3Button;
private JLabel debuggerPortOptionLabel;
private JLabel emptyLabel;
- private JLabel informationLabel;
private JLabel learnMoreLabel;
private JLabel messageTextLabel;
private JLabel noteLabel;
diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletion.java b/php/php.editor/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletion.java
index ec0f079..1c24d79 100644
--- a/php/php.editor/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletion.java
+++ b/php/php.editor/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletion.java
@@ -2166,7 +2166,7 @@
Token t = ts.token();
if (t != null) {
if (t.id() == PHPTokenId.T_INLINE_HTML) {
- return QueryType.ALL_COMPLETION;
+ return QueryType.NONE;
} else {
if (AUTOPOPUP_STOP_CHARS.contains(Character.valueOf(lastChar))) {
return QueryType.STOP;
diff --git a/platform/libs.flatlaf/external/binaries-list b/platform/libs.flatlaf/external/binaries-list
index dbbd79a..22a0c39 100644
--- a/platform/libs.flatlaf/external/binaries-list
+++ b/platform/libs.flatlaf/external/binaries-list
@@ -15,4 +15,4 @@
# specific language governing permissions and limitations
# under the License.
-1E93E3D19E4FFFAB2BB9AF96A6D47BBB7B3AB1CE com.formdev:flatlaf:1.4
+D5AD617D7C328784145B05F7C8F030DB2DE5234E com.formdev:flatlaf:1.5
diff --git a/platform/libs.flatlaf/external/flatlaf-1.4-license.txt b/platform/libs.flatlaf/external/flatlaf-1.5-license.txt
similarity index 99%
rename from platform/libs.flatlaf/external/flatlaf-1.4-license.txt
rename to platform/libs.flatlaf/external/flatlaf-1.5-license.txt
index 93beceb..271cdda 100644
--- a/platform/libs.flatlaf/external/flatlaf-1.4-license.txt
+++ b/platform/libs.flatlaf/external/flatlaf-1.5-license.txt
@@ -1,7 +1,7 @@
Name: FlatLaf Look and Feel
Description: FlatLaf Look and Feel
-Version: 1.4
-Files: flatlaf-1.4.jar
+Version: 1.5
+Files: flatlaf-1.5.jar
License: Apache-2.0
Origin: FormDev Software GmbH.
URL: https://www.formdev.com/flatlaf/
diff --git a/platform/libs.flatlaf/nbproject/project.properties b/platform/libs.flatlaf/nbproject/project.properties
index 2eced85..afe9131 100644
--- a/platform/libs.flatlaf/nbproject/project.properties
+++ b/platform/libs.flatlaf/nbproject/project.properties
@@ -20,4 +20,4 @@
javac.source=1.8
nbm.target.cluster=platform
-release.external/flatlaf-1.4.jar=modules/ext/flatlaf-1.4.jar
+release.external/flatlaf-1.5.jar=modules/ext/flatlaf-1.5.jar
diff --git a/platform/libs.flatlaf/nbproject/project.xml b/platform/libs.flatlaf/nbproject/project.xml
index ac57929..4469760 100644
--- a/platform/libs.flatlaf/nbproject/project.xml
+++ b/platform/libs.flatlaf/nbproject/project.xml
@@ -30,8 +30,8 @@
<package>com.formdev.flatlaf.util</package>
</public-packages>
<class-path-extension>
- <runtime-relative-path>ext/flatlaf-1.4.jar</runtime-relative-path>
- <binary-origin>external/flatlaf-1.4.jar</binary-origin>
+ <runtime-relative-path>ext/flatlaf-1.5.jar</runtime-relative-path>
+ <binary-origin>external/flatlaf-1.5.jar</binary-origin>
</class-path-extension>
</data>
</configuration>
diff --git a/platform/openide.actions/src/org/openide/actions/HeapView.java b/platform/openide.actions/src/org/openide/actions/HeapView.java
index a3bd5fb..0f4b13f 100644
--- a/platform/openide.actions/src/org/openide/actions/HeapView.java
+++ b/platform/openide.actions/src/org/openide/actions/HeapView.java
@@ -54,7 +54,7 @@
* <li> nb.heapview.background - Color of widget background
* <li> nb.heapview.foreground - Color of text
* <li> nb.heapview.chart - Color of area chart
- * <li> nb.heapview.background - Color of outline around the text, to provide a contrast against
+ * <li> nb.heapview.highlight - Color of outline around the text, to provide a contrast against
* the chart (may have a non-opaque alpha value)
* </ul>
* @author sky, radim, peter
@@ -112,17 +112,20 @@
}
TEXT_COLOR = c;
- c = UIManager.getColor("nb.heapview.highlight"); //NOI18N
- if (null == c) {
- c = new Color(255, 255, 255, 192);
- }
- OUTLINE_COLOR = c;
-
c = UIManager.getColor("nb.heapview.background"); //NOI18N
if (null == c) {
c = new Color(0xCEDBE6);
}
BACKGROUND_COLOR = c;
+
+ c = UIManager.getColor("nb.heapview.highlight"); //NOI18N
+ if (null == c) {
+ c = new Color(BACKGROUND_COLOR.getRed(),
+ BACKGROUND_COLOR.getGreen(),
+ BACKGROUND_COLOR.getBlue(),
+ 192);
+ }
+ OUTLINE_COLOR = c;
}
/**
diff --git a/profiler/profiler.nbimpl/nbproject/project.xml b/profiler/profiler.nbimpl/nbproject/project.xml
index e9e8579..7cfecd1 100644
--- a/profiler/profiler.nbimpl/nbproject/project.xml
+++ b/profiler/profiler.nbimpl/nbproject/project.xml
@@ -129,7 +129,7 @@
<compile-dependency/>
<run-dependency>
<release-version>2</release-version>
- <specification-version>1.30</specification-version>
+ <specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
diff --git a/profiler/profiler.nbimpl/src/org/netbeans/modules/profiler/nbimpl/providers/DefaultProfilerArgsProvider.java b/profiler/profiler.nbimpl/src/org/netbeans/modules/profiler/nbimpl/providers/DefaultProfilerArgsProvider.java
index 65e045b..9bdbad7 100644
--- a/profiler/profiler.nbimpl/src/org/netbeans/modules/profiler/nbimpl/providers/DefaultProfilerArgsProvider.java
+++ b/profiler/profiler.nbimpl/src/org/netbeans/modules/profiler/nbimpl/providers/DefaultProfilerArgsProvider.java
@@ -24,6 +24,7 @@
import org.netbeans.api.project.Project;
import org.netbeans.modules.profiler.nbimpl.actions.ProfilerLauncher;
import org.netbeans.spi.extexecution.startup.StartupExtenderImplementation;
+import org.openide.util.BaseUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
@@ -34,7 +35,7 @@
@NbBundle.Messages({
"DESC_NBProfiler=NetBeans Profiler"
})
-@StartupExtenderImplementation.Registration(displayName="#DESC_NBProfiler", position=1000, startMode={
+@StartupExtenderImplementation.Registration(displayName="#DESC_NBProfiler", position=1000, argumentsQuoted = false, startMode={
StartupExtender.StartMode.PROFILE,
StartupExtender.StartMode.TEST_PROFILE
})
@@ -50,7 +51,8 @@
List<String> args = new ArrayList<String>();
String agentArgs = m.get("agent.jvmargs"); // NOI18N // Always set
- args.add(agentArgs);
+ // remove quoting, expand params to array
+ args.addAll(Arrays.asList(BaseUtilities.parseParameters(agentArgs)[0]));
String jvmargs = m.get("profiler.info.jvmargs"); // NOI18N // May not be set
if (jvmargs != null) {
@@ -59,11 +61,13 @@
while (st.hasMoreTokens()) {
String arg = st.nextToken();
if (!arg.isEmpty()) {
- args.add((arg.startsWith("-") ? "" : "-") + arg); // NOI18N
+ // remove any quoting etc, there should be just a single parameter.
+ for (String a : BaseUtilities.parseParameters(arg)) {
+ args.add((arg.startsWith("-") ? "" : "-") + a); // NOI18N
+ }
}
}
}
-
return args;
}
}
diff --git a/webcommon/javascript.nodejs/src/org/netbeans/modules/javascript/nodejs/exec/NodeExecutable.java b/webcommon/javascript.nodejs/src/org/netbeans/modules/javascript/nodejs/exec/NodeExecutable.java
index 227124c..f392b21 100644
--- a/webcommon/javascript.nodejs/src/org/netbeans/modules/javascript/nodejs/exec/NodeExecutable.java
+++ b/webcommon/javascript.nodejs/src/org/netbeans/modules/javascript/nodejs/exec/NodeExecutable.java
@@ -359,7 +359,7 @@
List<String> params = new ArrayList<>();
List<StartupExtender> extenders = StartupExtender.getExtenders(project.getLookup(), StartupExtender.StartMode.DEBUG);
for (StartupExtender e : extenders) {
- params.addAll(e.getArguments());
+ params.addAll(e.getRawArguments());
}
if (params.isEmpty()) {
params.add(String.format(getDebugCommand(), port));