Skip to content

Commit 5c3228f

Browse files
committed
StaticImport hint should support records and other class kinds
uses javac's Element.getKind().isDeclaredType() as filter which matches all class kinds (interfaces, records etc). minor code improvements and indentation fixes
1 parent dedef60 commit 5c3228f

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)