Skip to content

Commit 594cda5

Browse files
committed
Updated the JavaLangFeatures feature name extractor to work with JDK25+ EA
Updated the code to obtain the parent diagnostics keys for feature-related errors/warnings to be agnostic to movement across different diagnostic types in different JDKs. For example, Warning -> LinterWarning
1 parent 80af1a5 commit 594cda5

File tree

2 files changed

+87
-27
lines changed

2 files changed

+87
-27
lines changed

nbcode/telemetry/src/org/netbeans/modules/nbcode/java/lsp/server/telemetry/JavaLangFeatures.java

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,20 @@
1818
import com.sun.tools.javac.code.Source;
1919
import com.sun.tools.javac.resources.CompilerProperties;
2020
import com.sun.tools.javac.util.JCDiagnostic;
21+
import java.lang.reflect.Method;
22+
import java.lang.reflect.Modifier;
23+
import java.util.Arrays;
2124
import java.util.Collections;
2225
import java.util.HashMap;
2326
import java.util.HashSet;
2427
import java.util.Map;
2528
import java.util.Set;
29+
import java.util.function.Consumer;
30+
import java.util.logging.Level;
31+
import java.util.logging.Logger;
2632

2733
class JavaLangFeatures {
34+
private static final Logger LOG = Logger.getLogger(JavaLangFeatures.class.getName());
2835

2936
public static boolean isDiagnosticForUnsupportedFeatures(String diagnosticCode) {
3037
return Singleton.javacParentDiagnosticKeys.contains(diagnosticCode);
@@ -47,45 +54,98 @@ private static class Singleton {
4754
static {
4855
Map<String, Source.Feature> featureFragments = new HashMap<>();
4956
Set<String> parentDiagnosticKeys = new HashSet<>();
50-
String prefix = "compiler.misc.";
57+
String prefix = null;
5158
try {
52-
final JCDiagnostic.Fragment fragment = CompilerProperties.Fragments.FeatureNotSupportedInSource((JCDiagnostic) null, null, null);
53-
final String fragmentKey = fragment.key();
54-
final String fragmentCode = fragment.getCode();
55-
if (fragmentKey.startsWith(fragmentCode)) {
56-
prefix = fragmentKey.substring(fragmentCode.length());
57-
}
58-
59-
parentDiagnosticKeys.add(fragmentKey);
60-
parentDiagnosticKeys.add(CompilerProperties.Fragments.FeatureNotSupportedInSourcePlural((JCDiagnostic) null, null, null).key());
61-
parentDiagnosticKeys.add(CompilerProperties.Errors.FeatureNotSupportedInSource((JCDiagnostic) null, null, null).key());
62-
parentDiagnosticKeys.add(CompilerProperties.Errors.FeatureNotSupportedInSourcePlural((JCDiagnostic) null, null, null).key());
63-
64-
parentDiagnosticKeys.add(CompilerProperties.Errors.PreviewFeatureDisabled((JCDiagnostic) null).key());
65-
parentDiagnosticKeys.add(CompilerProperties.Errors.PreviewFeatureDisabledPlural((JCDiagnostic) null).key());
66-
parentDiagnosticKeys.add(CompilerProperties.Warnings.PreviewFeatureUse((JCDiagnostic) null).key());
67-
parentDiagnosticKeys.add(CompilerProperties.Warnings.PreviewFeatureUsePlural((JCDiagnostic) null).key());
68-
69-
parentDiagnosticKeys.add(CompilerProperties.Errors.IsPreview(null).key());
70-
parentDiagnosticKeys.add(CompilerProperties.Warnings.IsPreview(null).key());
71-
parentDiagnosticKeys.add(CompilerProperties.Warnings.IsPreviewReflective(null).key());
72-
7359
for (Source.Feature f : Source.Feature.values()) {
7460
try {
75-
featureFragments.put(f.nameFragment().getCode(), f);
61+
JCDiagnostic.Fragment nameFragment = f.nameFragment();
62+
featureFragments.put(nameFragment.getCode(), f);
63+
64+
if (prefix == null) {
65+
final String fragmentKey = nameFragment.key();
66+
final String fragmentCode = nameFragment.getCode();
67+
if (fragmentCode.length() > 0 && fragmentKey.endsWith(fragmentCode)) {
68+
prefix = fragmentKey.substring(0, fragmentKey.length() - fragmentCode.length());
69+
}
70+
}
7671
} catch (AssertionError | NullPointerException e) {
7772
// In case no error message code has been registered; for example: LOCAL_VARIABLE_TYPE_INFERENCE
7873
featureFragments.put(f.name(), f);
7974
}
8075
}
76+
77+
Set<String> diagnosticMethodNames = new HashSet<>(Arrays.asList(
78+
"FeatureNotSupportedInSource",
79+
"FeatureNotSupportedInSourcePlural",
80+
"PreviewFeatureDisabled",
81+
"PreviewFeatureDisabledPlural",
82+
"PreviewFeatureUse",
83+
"PreviewFeatureUsePlural",
84+
"IsPreview",
85+
"IsPreviewReflective"
86+
));
87+
supplyKeyForEachDiagnosticName(diagnosticMethodNames, parentDiagnosticKeys::add);
8188
} catch (VirtualMachineError e) {
8289
throw e;
83-
} catch (Throwable ignore) {
90+
} catch (Throwable e) {
91+
try {
92+
LOG.log(Level.CONFIG, "Unexpected error initialising Java Language features and parent diagnostic codes: {0}", (Object) e);
93+
} catch (Throwable ignore) {
94+
}
8495
}
85-
javacFragmentCodePrefix = prefix;
96+
javacFragmentCodePrefix = prefix == null ? "compiler.misc." : prefix;
8697
javacParentDiagnosticKeys = parentDiagnosticKeys.isEmpty() ? Collections.emptySet() : Collections.unmodifiableSet(parentDiagnosticKeys);
8798
fragmentCodeToFeature = featureFragments.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(featureFragments);
8899
}
100+
101+
private static void supplyKeyForEachDiagnosticName(Set<String> methodNames, Consumer<String> action) {
102+
if (methodNames == null || methodNames.isEmpty()) return;
103+
final Object[][] emptyArgs = new Object[6][];
104+
for (int i = 0; i < emptyArgs.length; i++) {
105+
emptyArgs[i] = new Object[i];
106+
}
107+
int numInitErrors = 0;
108+
Class<?>[] classes = CompilerProperties.class.getClasses();
109+
for (Class<?> nestedClass : classes) {
110+
Method[] methods = Modifier.isStatic(nestedClass.getModifiers()) ? nestedClass.getMethods() : null;
111+
if (methods == null || methods.length == 0) {
112+
continue;
113+
}
114+
for (Method m : methods) {
115+
try {
116+
if (Modifier.isStatic(m.getModifiers())
117+
&& JCDiagnostic.DiagnosticInfo.class.isAssignableFrom(m.getReturnType())
118+
&& methodNames.contains(m.getName())) {
119+
int numParams = m.getParameterCount();
120+
JCDiagnostic.DiagnosticInfo diag = (JCDiagnostic.DiagnosticInfo) m.invoke(null, numParams < emptyArgs.length ? emptyArgs[numParams] : Arrays.copyOf(emptyArgs[0], numParams));
121+
if (diag != null) {
122+
action.accept(diag.key());
123+
}
124+
}
125+
} catch (VirtualMachineError e) {
126+
throw e;
127+
} catch (Throwable e) {
128+
numInitErrors++;
129+
try {
130+
String name = null;
131+
try {
132+
name = m.getName();
133+
} catch (Throwable ignore) {
134+
}
135+
LOG.log(Level.FINE, "Unexpected error initialising diagnostic key for method \"{1}\", related to Java Language features: {0}",
136+
name == null ? new Object[]{e, m} : new Object[]{e, name});
137+
} catch (Throwable ignore) {
138+
}
139+
}
140+
}
141+
}
142+
if (numInitErrors > 0 && !LOG.isLoggable(Level.FINE)) {
143+
try {
144+
LOG.log(Level.CONFIG, "Unexpected {0} error(s) initialising diagnostic keys for methods related to Java Language features.", numInitErrors);
145+
} catch (Throwable ignore) {
146+
}
147+
}
148+
}
89149
}
90150

91151
}

nbcode/telemetry/src/org/netbeans/modules/nbcode/java/lsp/server/telemetry/JavaLanguageFeaturesEmitter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ Set<String> checkJavaFeatures() {
7474
task = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, dl, List.of("--source", "8", "--source-path", sourceInfo.getSourcesPath()), null, List.of(sourceInfo.source));
7575
task.analyze();
7676
} catch (IOException e) {
77-
LOG.log(Level.FINE, "IO error while scanning Java Language features: {0}", e);
77+
LOG.log(Level.FINE, "IO error while scanning Java Language features: {0}", (Object) e);
7878
} catch (IllegalArgumentException e) {
79-
LOG.log(Level.CONFIG, "Invalid parsing parameters for scanning Java Language features: {0}", e);
79+
LOG.log(Level.CONFIG, "Invalid parsing parameters for scanning Java Language features: {0}", (Object) e);
8080
} catch (RuntimeException ignored) {
8181
}
8282
return featuresUsed;

0 commit comments

Comments
 (0)