Skip to content

Commit a3a514c

Browse files
committedFeb 6, 2025
7903934: Add support for query strings to the IntelliJ plugin
Reviewed-by: mcimadamore
1 parent 3865c9f commit a3a514c

8 files changed

+164
-35
lines changed
 

‎.github/workflows/gradle-wrapper-validation.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ jobs:
1111
runs-on: ubuntu-latest
1212
steps:
1313
- uses: actions/checkout@v4
14-
- uses: gradle/wrapper-validation-action@v3
14+
- uses: gradle/actions/wrapper-validation@v4

‎plugins/idea/gradle.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ ideVersion = 2024.2.0.2
44
minBuild = IC-242.20224.419
55
# https://plugins.jetbrains.com/plugin/23025-ant
66
antSupportVersion = 242.20224.159
7-
pluginVersion = 1.17
7+
pluginVersion = 1.18
88
javaLevel = 21
99
notes = <ul>\
10-
<li>CODETOOLS-7903744: Update various versions used by jtreg IDEA plugin</li>\
10+
<li>CODETOOLS-7903934: Add support for query strings to the IntelliJ plugin</li>\
1111
</ul>

‎plugins/idea/src/main/java/com/oracle/plugin/jtreg/configuration/JTRegConfiguration.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -70,6 +70,7 @@ public class JTRegConfiguration extends JavaTestConfigurationBase {
7070
private boolean alternativeJrePathEnabled;
7171
private String alternativeJrePath;
7272
private String file;
73+
private String query;
7374
private String directory;
7475
private String workDirectory;
7576

@@ -218,6 +219,14 @@ public void setRunClass(String file) {
218219
this.file = file;
219220
}
220221

222+
public String getQuery() {
223+
return query;
224+
}
225+
226+
public void setQuery(String query) {
227+
this.query = query;
228+
}
229+
221230
@Nullable
222231
@Override
223232
public String getPackage() {

‎plugins/idea/src/main/java/com/oracle/plugin/jtreg/configuration/JTRegConfigurationRunnableState.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
2828
import com.intellij.execution.*;
2929
import com.intellij.execution.configurations.JavaParameters;
3030
import com.intellij.execution.configurations.ParametersList;
31-
import com.intellij.execution.configurations.RuntimeConfigurationError;
3231
import com.intellij.execution.configurations.RuntimeConfigurationException;
3332
import com.intellij.execution.process.KillableColoredProcessHandler;
3433
import com.intellij.execution.process.OSProcessHandler;
@@ -37,16 +36,11 @@
3736
import com.intellij.execution.runners.ProgramRunner;
3837
import com.intellij.execution.testframework.SearchForTestsTask;
3938
import com.intellij.execution.testframework.TestSearchScope;
40-
import com.intellij.execution.ui.DefaultJreSelector;
4139
import com.intellij.openapi.module.Module;
42-
import com.intellij.openapi.projectRoots.JdkUtil;
43-
import com.intellij.openapi.projectRoots.ProjectJdkTable;
44-
import com.intellij.openapi.projectRoots.Sdk;
4540
import com.intellij.util.PathUtil;
4641
import org.jetbrains.annotations.NotNull;
4742
import org.jetbrains.annotations.Nullable;
4843
import com.oracle.plugin.jtreg.executors.JTRegDebuggerRunner;
49-
import com.oracle.plugin.jtreg.runtime.JTRegTestListener;
5044
import com.oracle.plugin.jtreg.service.JTRegService;
5145

5246
import java.io.File;
@@ -148,7 +142,11 @@ protected JavaParameters createJavaParameters() throws ExecutionException {
148142
javaParameters.getProgramParametersList().add("-o:com.oracle.plugin.jtreg.runtime.JTRegTestListener");
149143
javaParameters.getProgramParametersList().add("-od:" + PathUtil.getJarPathForClass(JTRegConfiguration.class));
150144
if (getConfiguration().getRunClass() != null) {
151-
javaParameters.getProgramParametersList().add(getConfiguration().getRunClass());
145+
if (getConfiguration().getQuery() != null && !getConfiguration().getQuery().isEmpty()) {
146+
javaParameters.getProgramParametersList().add(getConfiguration().getRunClass() + "?" + getConfiguration().getQuery());
147+
} else {
148+
javaParameters.getProgramParametersList().add(getConfiguration().getRunClass());
149+
}
152150
} else {
153151
javaParameters.getProgramParametersList().add(getConfiguration().getPackage());
154152
}

‎plugins/idea/src/main/java/com/oracle/plugin/jtreg/configuration/producers/JTRegClassConfigurationProducer.java

+21-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,15 +27,12 @@
2727

2828
import com.intellij.execution.Location;
2929
import com.intellij.execution.actions.ConfigurationContext;
30-
import com.intellij.lang.ant.config.AntConfiguration;
3130
import com.intellij.openapi.module.Module;
3231
import com.intellij.openapi.util.Ref;
3332
import com.intellij.psi.*;
3433
import com.oracle.plugin.jtreg.configuration.JTRegConfiguration;
3534
import com.oracle.plugin.jtreg.service.JTRegService;
3635
import com.oracle.plugin.jtreg.util.JTRegUtils;
37-
import com.oracle.plugin.jtreg.configuration.JTRegConfiguration;
38-
import com.oracle.plugin.jtreg.service.JTRegService;
3936

4037
/**
4138
* This class generates a jtreg configuration from a given file selected in the IDE.
@@ -44,8 +41,10 @@ public class JTRegClassConfigurationProducer extends JTRegConfigurationProducer
4441

4542
@Override
4643
protected boolean setupConfigurationFromContext(JTRegConfiguration configuration, ConfigurationContext context, Ref<PsiElement> sourceElement) {
47-
final Location contextLocation = context.getLocation();
44+
final Location<PsiElement> contextLocation = context.getLocation();
4845
assert contextLocation != null;
46+
final PsiElement element = contextLocation.getPsiElement();
47+
4948
PsiFile psiFile = contextLocation.getPsiElement().getContainingFile();
5049
if (psiFile == null ||
5150
!JTRegUtils.isInJTRegRoot(psiFile.getContainingDirectory()) ||
@@ -59,8 +58,24 @@ protected boolean setupConfigurationFromContext(JTRegConfiguration configuration
5958
configuration.setWorkingDirectory(JTRegService.getInstance(configuration.getProject()).getWorkDir());
6059
configuration.setRunClass(psiFile.getVirtualFile().getPath());
6160
configuration.restoreOriginalModule(originalModule);
62-
configuration.setName(psiFile.getName());
61+
62+
configuration.setQuery(getQuery(element));
63+
configuration.setName(nameForElement(element));
64+
6365
initBeforeTaskActions(configuration);
6466
return true;
6567
}
68+
69+
private static String nameForElement(PsiElement element) {
70+
if (element instanceof PsiIdentifier
71+
&& element.getParent() instanceof PsiMethod method) {
72+
String className = ((PsiClass) method.getParent()).getQualifiedName();
73+
return className + "::" + method.getName();
74+
} else if (element instanceof PsiIdentifier
75+
&& element.getParent() instanceof PsiClass cls) {
76+
return cls.getQualifiedName();
77+
} else {
78+
return element.getContainingFile().getName();
79+
}
80+
}
6681
}

‎plugins/idea/src/main/java/com/oracle/plugin/jtreg/configuration/producers/JTRegConfigurationProducer.java

+93-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,13 +36,15 @@
3636
import com.intellij.lang.ant.config.*;
3737
import com.intellij.lang.ant.config.impl.AntBeforeRunTask;
3838
import com.intellij.lang.ant.config.impl.AntBeforeRunTaskProvider;
39-
import com.intellij.psi.PsiFile;
39+
import com.intellij.psi.*;
4040
import com.oracle.plugin.jtreg.configuration.JTRegConfiguration;
4141
import com.oracle.plugin.jtreg.service.JTRegService;
4242
import com.oracle.plugin.jtreg.configuration.JTRegConfigurationType;
43+
import com.oracle.plugin.jtreg.util.JTRegUtils;
4344
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
4445

4546
import java.util.List;
47+
import java.util.StringJoiner;
4648
import java.util.stream.Collectors;
4749

4850
/**
@@ -65,10 +67,95 @@ public boolean isConfigurationFromContext(JTRegConfiguration unitConfiguration,
6567
if (location == null) {
6668
return false;
6769
}
68-
PsiFile testClass = location.getPsiElement().getContainingFile();
69-
final String runClass = unitConfiguration.getRunClass();
70-
return runClass != null && testClass != null && testClass.getVirtualFile() != null &&
71-
runClass.equals(testClass.getVirtualFile().getPath());
70+
71+
PsiElement element = location.getPsiElement();
72+
String query = getQuery(element);
73+
PsiFile contextFile = element.getContainingFile();
74+
final String configFile = unitConfiguration.getRunClass();
75+
return configFile != null && contextFile != null && contextFile.getVirtualFile() != null &&
76+
configFile.equals(contextFile.getVirtualFile().getPath())
77+
&& query.equals(unitConfiguration.getQuery());
78+
}
79+
80+
protected static String getQuery(PsiElement element) {
81+
boolean isJUnit = JTRegUtils.isJUnitTestData(element.getContainingFile());
82+
boolean isTestNG = JTRegUtils.isTestNGTestData(element.getContainingFile());
83+
if (element instanceof PsiIdentifier
84+
&& element.getParent() instanceof PsiMethod method) {
85+
if (isJUnit) {
86+
return "junit-select:method:" + getJUnitMethodQuery(method);
87+
} else if (isTestNG) {
88+
// just the method name for TestNG
89+
return method.getName();
90+
}
91+
} else if (isJUnit && element instanceof PsiIdentifier
92+
&& element.getParent() instanceof PsiClass cls) {
93+
return "junit-select:class:" + binaryNameFor(cls);
94+
}
95+
return "";
96+
}
97+
98+
private static String getJUnitMethodQuery(PsiMethod method) {
99+
StringJoiner paramTypeNames = new StringJoiner(",");
100+
PsiParameterList params = method.getParameterList();
101+
for (int i = 0; i < params.getParametersCount(); i++) {
102+
PsiParameter param = params.getParameter(i);
103+
PsiType type = param.getType();
104+
paramTypeNames.add(binaryNameFor(type));
105+
}
106+
String className = binaryNameFor(((PsiClass) method.getParent()));
107+
return className + "#" + method.getName() + '(' + paramTypeNames + ')';
108+
}
109+
110+
private static String binaryNameFor(PsiType type) {
111+
if (type instanceof PsiPrimitiveType) {
112+
return type.getCanonicalText();
113+
} else if (type instanceof PsiClassType clsType) {
114+
return binaryNameFor(clsType.resolve());
115+
} else if (type instanceof PsiArrayType arrayType) {
116+
return binaryNameFor(arrayType);
117+
} else {
118+
return type.getCanonicalText();
119+
}
120+
}
121+
122+
private static String binaryNameFor(PsiClass cls) {
123+
// handle nested classes. Convert '.' to '$'
124+
String nestedName = cls.getName();
125+
PsiClass current = cls;
126+
while ((current = current.getContainingClass()) != null) {
127+
nestedName = current.getName() + "." + nestedName;
128+
}
129+
String qualName = cls.getQualifiedName();
130+
String packageName = qualName.substring(0, qualName.length() - nestedName.length());
131+
return packageName + nestedName.replace('.', '$');
132+
}
133+
134+
private static String binaryNameFor(PsiArrayType arrayType) {
135+
PsiType component = arrayType.getDeepComponentType();
136+
String componentName;
137+
if (component instanceof PsiPrimitiveType primitiveType) {
138+
componentName = descriptorFor(primitiveType);
139+
} else if (component instanceof PsiClassType clsType) {
140+
componentName = "L" + binaryNameFor(clsType.resolve()) + ";";
141+
} else {
142+
componentName = component.getCanonicalText();
143+
}
144+
return "[".repeat(arrayType.getArrayDimensions()) + componentName;
145+
}
146+
147+
private static String descriptorFor(PsiPrimitiveType primitiveType) {
148+
return switch (primitiveType.getCanonicalText()) {
149+
case "boolean" -> "Z";
150+
case "byte" -> "B";
151+
case "char" -> "C";
152+
case "short" -> "S";
153+
case "int" -> "I";
154+
case "long" -> "J";
155+
case "float" -> "F";
156+
case "double" -> "D";
157+
default -> primitiveType.getCanonicalText();
158+
};
72159
}
73160

74161
@Override

‎plugins/idea/src/main/java/com/oracle/plugin/jtreg/configuration/ui/JTRegConfigurable.form

+26-10
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.oracle.plugin.jtreg.configuration.ui.JTRegConfigurable">
3-
<grid id="27dc6" binding="mainPane" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
3+
<grid id="27dc6" binding="mainPane" layout-manager="GridLayoutManager" row-count="7" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
44
<margin top="0" left="0" bottom="0" right="0"/>
55
<constraints>
6-
<xy x="20" y="20" width="418" height="227"/>
6+
<xy x="20" y="20" width="418" height="253"/>
77
</constraints>
88
<properties/>
99
<border type="none"/>
1010
<children>
1111
<component id="62dc1" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="workDirectory" custom-create="true">
1212
<constraints>
13-
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
13+
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
1414
</constraints>
1515
<properties/>
1616
</component>
1717
<component id="f22" class="javax.swing.JTextField" binding="jtregOptions">
1818
<constraints>
19-
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false">
19+
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false">
2020
<preferred-size width="150" height="-1"/>
2121
</grid>
2222
</constraints>
2323
<properties/>
2424
</component>
2525
<component id="26f59" class="com.intellij.execution.ui.JrePathEditor" binding="jrePathEditor" custom-create="true">
2626
<constraints>
27-
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
27+
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
2828
</constraints>
2929
<properties/>
3030
</component>
3131
<vspacer id="cfbe2">
3232
<constraints>
33-
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
33+
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
3434
</constraints>
3535
</vspacer>
3636
<component id="d8563" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="file" custom-create="true">
@@ -41,13 +41,13 @@
4141
</component>
4242
<component id="d511b" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="directory" custom-create="true">
4343
<constraints>
44-
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
44+
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
4545
</constraints>
4646
<properties/>
4747
</component>
4848
<component id="690e3" class="javax.swing.JLabel">
4949
<constraints>
50-
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
50+
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
5151
<preferred-size width="128" height="18"/>
5252
</grid>
5353
</constraints>
@@ -57,7 +57,7 @@
5757
</component>
5858
<component id="30df8" class="javax.swing.JLabel">
5959
<constraints>
60-
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
60+
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
6161
<preferred-size width="128" height="18"/>
6262
</grid>
6363
</constraints>
@@ -77,14 +77,30 @@
7777
</component>
7878
<component id="6ec22" class="javax.swing.JRadioButton" binding="directoryRadioButton" default-binding="true">
7979
<constraints>
80-
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
80+
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
8181
<preferred-size width="128" height="28"/>
8282
</grid>
8383
</constraints>
8484
<properties>
8585
<text value="Directory"/>
8686
</properties>
8787
</component>
88+
<component id="7994" class="javax.swing.JTextField" binding="jtregQuery">
89+
<constraints>
90+
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
91+
<preferred-size width="150" height="-1"/>
92+
</grid>
93+
</constraints>
94+
<properties/>
95+
</component>
96+
<component id="4cee6" class="javax.swing.JLabel">
97+
<constraints>
98+
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
99+
</constraints>
100+
<properties>
101+
<text value="Query string"/>
102+
</properties>
103+
</component>
88104
</children>
89105
</grid>
90106
<buttonGroups>

‎plugins/idea/src/main/java/com/oracle/plugin/jtreg/configuration/ui/JTRegConfigurable.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@
4343
* This class models the dialog associated with the (project-wide) jtreg tool settings.
4444
*/
4545
public class JTRegConfigurable<T extends JTRegConfiguration> extends SettingsEditor<T> {
46+
private JTextField jtregQuery;
4647
private JTextField jtregOptions;
4748
private TextFieldWithBrowseButton jtregDir;
4849
private TextFieldWithBrowseButton workDirectory;
@@ -78,6 +79,7 @@ private void createUIComponents() {
7879

7980
private void updateComponents(ActionEvent _unused) {
8081
file.setEnabled(fileRadioButton.isSelected());
82+
jtregQuery.setEnabled(fileRadioButton.isSelected());
8183
directory.setEnabled(directoryRadioButton.isSelected());
8284
}
8385

@@ -90,6 +92,7 @@ public void applyEditorTo(final JTRegConfiguration configuration) {
9092
configuration.setPackage(directoryRadioButton.isSelected() ?
9193
FileUtil.toSystemIndependentName(directory.getText().trim()) : null);
9294
configuration.setProgramParameters(jtregOptions.getText().trim());
95+
configuration.setQuery(jtregQuery.getText().trim());
9396
configuration.setWorkingDirectory(workDirectory.getText().isEmpty() ?
9497
null : FileUtil.toSystemIndependentName(workDirectory.getText().trim()));
9598
}
@@ -107,6 +110,7 @@ public void resetEditorFrom(final JTRegConfiguration configuration) {
107110
directory.setText(aPackage != null ? FileUtil.toSystemDependentName(aPackage) : null);
108111
}
109112
jtregOptions.setText(configuration.getProgramParameters());
113+
jtregQuery.setText(configuration.getQuery());
110114
String workDir = configuration.getWorkingDirectory();
111115
workDirectory.setText(workDir == null ? "" : FileUtil.toSystemDependentName(workDir));
112116
updateComponents(null);

0 commit comments

Comments
 (0)
Please sign in to comment.