Skip to content

Commit 5f03712

Browse files
authored
Merge pull request #9174 from mbien/static-import-hint-for-records_delivery
StaticImport hint should support records and other class kinds
2 parents fb954d4 + 5c3228f commit 5f03712

File tree

3 files changed

+34
-39
lines changed

3 files changed

+34
-39
lines changed

java/java.hints/src/org/netbeans/modules/java/hints/Bundle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,9 @@ HINT_SerialVersionUID_Generated=Add generated serialVersionUID
283283
FieldForUnusedParamCustomizer.finalFields.text=<html>Fields are <code>final</code></html>
284284
ACSD_Final_Fields=Make fields created by this hint final.
285285

286-
DSC_StaticImport=Convert a static method/field/enum-field reference to use a static import. Feedback to <a href="http://www.netbeans.org/issues/show_bug.cgi?id=89258">http://www.netbeans.org/issues/show_bug.cgi?id=89258</a>
286+
DSC_StaticImport=<html>Convert a static method/field/enum-field reference to use a static import.\
287+
<p><code>Math.abs(-1)</code> -> <code>abs(-1)</code></p><html>
288+
287289
DN_StaticImport=Static imports
288290
ERR_StaticImport=Convert to static import
289291
HINT_StaticImport=Convert {0} to static import

java/java.hints/src/org/netbeans/modules/java/hints/StaticImport.java

Lines changed: 19 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.sun.source.tree.Tree;
2929
import com.sun.source.tree.Tree.Kind;
3030
import com.sun.source.util.TreePath;
31-
import java.util.Collections;
3231
import java.util.EnumSet;
3332
import java.util.List;
3433
import java.util.Set;
@@ -42,7 +41,6 @@
4241
import javax.lang.model.type.TypeMirror;
4342
import javax.lang.model.util.Types;
4443
import org.netbeans.api.java.source.CompilationInfo;
45-
import org.netbeans.api.java.source.ElementUtilities;
4644
import org.netbeans.api.java.source.GeneratorUtilities;
4745
import org.netbeans.api.java.source.TreeMaker;
4846
import org.netbeans.api.java.source.TreePathHandle;
@@ -77,36 +75,36 @@
7775
*
7876
* @author Sam Halliday
7977
* @author markiewb
80-
* @see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=89258">RFE 89258</a>
81-
* @see <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html>Static Imports</a>
78+
* @see <a href="https://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html>Static Imports</a>
8279
*/
8380
@Hint(category="rules15", displayName="#DN_StaticImport", description="#DSC_StaticImport", severity=Severity.HINT, enabled=false, suppressWarnings={"", "StaticImport"},
8481
minSourceVersion = "5")
8582
public class StaticImport {
83+
84+
private static final Set<ElementKind> SUPPORTED_TYPES = EnumSet.of(ElementKind.METHOD, ElementKind.ENUM_CONSTANT, ElementKind.FIELD);
8685

8786
@TriggerTreeKind(Kind.MEMBER_SELECT)
8887
public static List<ErrorDescription> run(HintContext ctx) {
8988
CompilationInfo info = ctx.getInfo();
9089
TreePath treePath = ctx.getPath();
9190

9291
Element e = info.getTrees().getElement(treePath);
93-
EnumSet<ElementKind> supportedTypes = EnumSet.of(ElementKind.METHOD, ElementKind.ENUM_CONSTANT, ElementKind.FIELD);
94-
if (e == null || !e.getModifiers().contains(Modifier.STATIC) || !supportedTypes.contains(e.getKind())) {
92+
if (e == null || !e.getModifiers().contains(Modifier.STATIC) || !SUPPORTED_TYPES.contains(e.getKind())) {
9593
return null;
9694
}
9795

9896
if (ElementKind.METHOD == e.getKind()) {
9997
TreePath mitp = treePath.getParentPath();
10098
if (mitp == null || mitp.getLeaf().getKind() != Kind.METHOD_INVOCATION) {
101-
return null;
102-
}
99+
return null;
100+
}
103101
if (((MethodInvocationTree) mitp.getLeaf()).getMethodSelect() != treePath.getLeaf()) {
104-
return null;
105-
}
102+
return null;
103+
}
106104
List<? extends Tree> typeArgs = ((MethodInvocationTree) mitp.getLeaf()).getTypeArguments();
107105
if (typeArgs != null && !typeArgs.isEmpty()) {
108-
return null;
109-
}
106+
return null;
107+
}
110108
}
111109
Element enclosingEl = e.getEnclosingElement();
112110
if (enclosingEl == null) {
@@ -122,7 +120,7 @@ public static List<ErrorDescription> run(HintContext ctx) {
122120
return null;
123121
}
124122
Element klass = info.getTrees().getElement(cc);
125-
if (klass == null || klass.getKind() != ElementKind.CLASS) {
123+
if (klass == null || !klass.getKind().isDeclaredType()) {
126124
return null;
127125
}
128126
String fqn = null;
@@ -143,7 +141,7 @@ public static List<ErrorDescription> run(HintContext ctx) {
143141
if (ctx.isCanceled()) {
144142
return null;
145143
}
146-
return Collections.singletonList(ed);
144+
return List.of(ed);
147145
}
148146

149147
public static final class FixImpl extends JavaFix {
@@ -189,31 +187,18 @@ protected void performRewrite(TransformationContext ctx) throws Exception {
189187
return;
190188
}
191189
CompilationUnitTree cut = (CompilationUnitTree) copy.resolveRewriteTarget(copy.getCompilationUnit());
192-
CompilationUnitTree nue = GeneratorUtilities.get(copy).addImports(cut, Collections.singleton(e));
190+
CompilationUnitTree nue = GeneratorUtilities.get(copy).addImports(cut, Set.of(e));
193191
copy.rewrite(cut, nue);
194192
}
195193

196194
}
197195

198-
/**
199-
* @param info
200-
* @return true if the source level supports the static import language feature
201-
*/
202-
private static boolean supportsStaticImports(CompilationInfo info) {
203-
return info.getSourceVersion().compareTo(SourceVersion.RELEASE_5) >= 0;
204-
}
205-
206196
// returns true if a METHOD is enclosed in element with simple name sn
207197
private static boolean hasMethodWithSimpleName(CompilationInfo info, Element element, final String sn) {
208-
Iterable<? extends Element> members =
209-
info.getElementUtilities().getMembers(element.asType(), new ElementUtilities.ElementAcceptor() {
210-
211-
@Override
212-
public boolean accept(Element e, TypeMirror type) {
213-
return e.getKind() == ElementKind.METHOD && e.getSimpleName().toString().equals(sn);
214-
}
215-
});
216-
return members.iterator().hasNext();
198+
return info.getElementUtilities().getMembers(
199+
element.asType(),
200+
(elem, type) -> elem.getKind() == ElementKind.METHOD && elem.getSimpleName().toString().equals(sn)
201+
).iterator().hasNext();
217202
}
218203

219204
/**
@@ -266,7 +251,7 @@ private static boolean hasStaticImportSimpleNameClash(CompilationInfo info, Stri
266251
*/
267252
private static boolean isSubTypeOrInnerOfSubType(CompilationInfo info, Element t1, Element t2) {
268253
boolean isSubtype = info.getTypes().isSubtype(t1.asType(), t2.asType());
269-
boolean isInnerClass = t1.getEnclosingElement().getKind() == ElementKind.CLASS;
254+
boolean isInnerClass = t1.getEnclosingElement().getKind().isDeclaredType();
270255
return isSubtype || (isInnerClass && info.getTypes().isSubtype(t1.getEnclosingElement().asType(), t2.asType()));
271256
}
272257

@@ -278,15 +263,12 @@ private static boolean isSubTypeOrInnerOfSubType(CompilationInfo info, Element t
278263
* methods in klass (which may be an inner or static class).
279264
*/
280265
private static boolean hasMethodNameClash(CompilationInfo info, Element klass, String simpleName) {
281-
assert klass != null;
282-
assert klass.getKind() == ElementKind.CLASS;
283-
284266
// check the members and inherited members of the klass
285267
if (hasMethodWithSimpleName(info, klass, simpleName)) {
286268
return true;
287269
}
288270
Element klassEnclosing = klass.getEnclosingElement();
289-
return (klassEnclosing != null && klassEnclosing.getKind() == ElementKind.CLASS && hasMethodWithSimpleName(info, klassEnclosing, simpleName));
271+
return klassEnclosing != null && klassEnclosing.getKind().isDeclaredType() && hasMethodWithSimpleName(info, klassEnclosing, simpleName);
290272
}
291273

292274
/**

java/java.hints/test/unit/src/org/netbeans/modules/java/hints/StaticImportTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ public void testStaticImportHint1() throws Exception {
9999
String golden = "package test; import static java.lang.Math.abs; public class Test { public Test() { abs(1); } }";
100100
performFixTest(test, golden);
101101
}
102+
103+
public void testStaticImportHint1_InRecord() throws Exception {
104+
String test = "package test; public record Test(int n) { public Test { Math.|abs(n); } }";
105+
String golden = "package test; import static java.lang.Math.abs; public record Test(int n) { public Test { abs(n); } }";
106+
performFixTest(test, golden, 17);
107+
}
102108

103109
public void testStaticImportHint2() throws Exception {
104110
String test = "package test; public class Test { public Test() { Test.get|Logger(); } public static void getLogger() { } }";
@@ -161,17 +167,22 @@ public void testIgnoreClass() throws Exception {
161167
performAnalysisTest(test);
162168
}
163169

170+
private void performFixTest(String test, String golden) throws Exception {
171+
performFixTest(test, golden, 8);
172+
}
173+
164174
// test is single line source code for test.Test, | in the member select, space before
165175
// golden is the output to test against
166176
// sn is the simple name of the static method
167-
private void performFixTest(String test, String golden) throws Exception {
177+
private void performFixTest(String test, String golden, int level) throws Exception {
168178
int offset = test.indexOf("|");
169179
assertTrue(offset != -1);
170180
int end = test.indexOf("(", offset) - 1;
171181
assertTrue(end > 0);
172182
int start = test.lastIndexOf(" ", offset) + 1;
173183
assertTrue(start > 0);
174184
HintTest.create()
185+
.sourceLevel(level)
175186
.input(test.replace("|", ""))
176187
.run(StaticImport.class)
177188
.findWarning("0:" + start + "-0:" + end + ":hint:" + NbBundle.getMessage(StaticImport.class, "ERR_StaticImport"))

0 commit comments

Comments
 (0)