Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,20 @@
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.resources.CompilerProperties;
import com.sun.tools.javac.util.JCDiagnostic;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;

class JavaLangFeatures {
private static final Logger LOG = Logger.getLogger(JavaLangFeatures.class.getName());

public static boolean isDiagnosticForUnsupportedFeatures(String diagnosticCode) {
return Singleton.javacParentDiagnosticKeys.contains(diagnosticCode);
Expand All @@ -47,45 +54,98 @@ private static class Singleton {
static {
Map<String, Source.Feature> featureFragments = new HashMap<>();
Set<String> parentDiagnosticKeys = new HashSet<>();
String prefix = "compiler.misc.";
String prefix = null;
try {
final JCDiagnostic.Fragment fragment = CompilerProperties.Fragments.FeatureNotSupportedInSource((JCDiagnostic) null, null, null);
final String fragmentKey = fragment.key();
final String fragmentCode = fragment.getCode();
if (fragmentKey.startsWith(fragmentCode)) {
prefix = fragmentKey.substring(fragmentCode.length());
}

parentDiagnosticKeys.add(fragmentKey);
parentDiagnosticKeys.add(CompilerProperties.Fragments.FeatureNotSupportedInSourcePlural((JCDiagnostic) null, null, null).key());
parentDiagnosticKeys.add(CompilerProperties.Errors.FeatureNotSupportedInSource((JCDiagnostic) null, null, null).key());
parentDiagnosticKeys.add(CompilerProperties.Errors.FeatureNotSupportedInSourcePlural((JCDiagnostic) null, null, null).key());

parentDiagnosticKeys.add(CompilerProperties.Errors.PreviewFeatureDisabled((JCDiagnostic) null).key());
parentDiagnosticKeys.add(CompilerProperties.Errors.PreviewFeatureDisabledPlural((JCDiagnostic) null).key());
parentDiagnosticKeys.add(CompilerProperties.Warnings.PreviewFeatureUse((JCDiagnostic) null).key());
parentDiagnosticKeys.add(CompilerProperties.Warnings.PreviewFeatureUsePlural((JCDiagnostic) null).key());

parentDiagnosticKeys.add(CompilerProperties.Errors.IsPreview(null).key());
parentDiagnosticKeys.add(CompilerProperties.Warnings.IsPreview(null).key());
parentDiagnosticKeys.add(CompilerProperties.Warnings.IsPreviewReflective(null).key());

for (Source.Feature f : Source.Feature.values()) {
try {
featureFragments.put(f.nameFragment().getCode(), f);
JCDiagnostic.Fragment nameFragment = f.nameFragment();
featureFragments.put(nameFragment.getCode(), f);

if (prefix == null) {
final String fragmentKey = nameFragment.key();
final String fragmentCode = nameFragment.getCode();
if (fragmentCode.length() > 0 && fragmentKey.endsWith(fragmentCode)) {
prefix = fragmentKey.substring(0, fragmentKey.length() - fragmentCode.length());
}
}
} catch (AssertionError | NullPointerException e) {
// In case no error message code has been registered; for example: LOCAL_VARIABLE_TYPE_INFERENCE
featureFragments.put(f.name(), f);
}
}

Set<String> diagnosticMethodNames = new HashSet<>(Arrays.asList(
"FeatureNotSupportedInSource",
"FeatureNotSupportedInSourcePlural",
"PreviewFeatureDisabled",
"PreviewFeatureDisabledPlural",
"PreviewFeatureUse",
"PreviewFeatureUsePlural",
"IsPreview",
"IsPreviewReflective"
));
supplyKeyForEachDiagnosticName(diagnosticMethodNames, parentDiagnosticKeys::add);
} catch (VirtualMachineError e) {
throw e;
} catch (Throwable ignore) {
} catch (Throwable e) {
try {
LOG.log(Level.CONFIG, "Unexpected error initialising Java Language features and parent diagnostic codes: {0}", (Object) e);
} catch (Throwable ignore) {
}
}
javacFragmentCodePrefix = prefix;
javacFragmentCodePrefix = prefix == null ? "compiler.misc." : prefix;
javacParentDiagnosticKeys = parentDiagnosticKeys.isEmpty() ? Collections.emptySet() : Collections.unmodifiableSet(parentDiagnosticKeys);
fragmentCodeToFeature = featureFragments.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(featureFragments);
}

private static void supplyKeyForEachDiagnosticName(Set<String> methodNames, Consumer<String> action) {
if (methodNames == null || methodNames.isEmpty()) return;
final Object[][] emptyArgs = new Object[6][];
for (int i = 0; i < emptyArgs.length; i++) {
emptyArgs[i] = new Object[i];
}
int numInitErrors = 0;
Class<?>[] classes = CompilerProperties.class.getClasses();
for (Class<?> nestedClass : classes) {
Method[] methods = Modifier.isStatic(nestedClass.getModifiers()) ? nestedClass.getMethods() : null;
if (methods == null || methods.length == 0) {
continue;
}
for (Method m : methods) {
try {
if (Modifier.isStatic(m.getModifiers())
&& JCDiagnostic.DiagnosticInfo.class.isAssignableFrom(m.getReturnType())
&& methodNames.contains(m.getName())) {
int numParams = m.getParameterCount();
JCDiagnostic.DiagnosticInfo diag = (JCDiagnostic.DiagnosticInfo) m.invoke(null, numParams < emptyArgs.length ? emptyArgs[numParams] : Arrays.copyOf(emptyArgs[0], numParams));
if (diag != null) {
action.accept(diag.key());
}
}
} catch (VirtualMachineError e) {
throw e;
} catch (Throwable e) {
numInitErrors++;
try {
String name = null;
try {
name = m.getName();
} catch (Throwable ignore) {
}
LOG.log(Level.FINE, "Unexpected error initialising diagnostic key for method \"{1}\", related to Java Language features: {0}",
name == null ? new Object[]{e, m} : new Object[]{e, name});
} catch (Throwable ignore) {
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of ignoring, should we log using fine or finer level, so that for debugging purpose it will help?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added logger. Thanks.

}
}
if (numInitErrors > 0 && !LOG.isLoggable(Level.FINE)) {
try {
LOG.log(Level.CONFIG, "Unexpected {0} error(s) initialising diagnostic keys for methods related to Java Language features.", numInitErrors);
} catch (Throwable ignore) {
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ Set<String> checkJavaFeatures() {
task = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, dl, List.of("--source", "8", "--source-path", sourceInfo.getSourcesPath()), null, List.of(sourceInfo.source));
task.analyze();
} catch (IOException e) {
LOG.log(Level.FINE, "IO error while scanning Java Language features: {0}", e);
LOG.log(Level.FINE, "IO error while scanning Java Language features: {0}", (Object) e);
} catch (IllegalArgumentException e) {
LOG.log(Level.CONFIG, "Invalid parsing parameters for scanning Java Language features: {0}", e);
LOG.log(Level.CONFIG, "Invalid parsing parameters for scanning Java Language features: {0}", (Object) e);
} catch (RuntimeException ignored) {
}
return featuresUsed;
Expand Down