mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8359493: Refactor how aggregated mandatory warnings are handled in the compiler
8350514: Refactor MandatoryWarningHandler to support dynamic verbosity Reviewed-by: mcimadamore
This commit is contained in:
parent
a2315ddd2a
commit
25ed36f3ef
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,6 +47,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
@ -93,7 +94,9 @@ public class ClassGenerator {
|
||||
FACTORY_FIELD_LINT("factory.decl.field.lint"),
|
||||
WILDCARDS_EXTENDS("wildcards.extends"),
|
||||
SUPPRESS_WARNINGS("suppress.warnings"),
|
||||
LINT_CATEGORY("lint.category");
|
||||
LINT_CATEGORY("lint.category"),
|
||||
DIAGNOSTIC_FLAGS_EMPTY("diagnostic.flags.empty"),
|
||||
DIAGNOSTIC_FLAGS_NON_EMPTY("diagnostic.flags.non-empty");
|
||||
|
||||
/** stub key (as it appears in the property file) */
|
||||
String key;
|
||||
@ -259,17 +262,30 @@ public class ClassGenerator {
|
||||
.map(MessageLine::lintCategory)
|
||||
.findFirst().orElse(null);
|
||||
//System.out.println("category for " + key + " = " + lintCategory);
|
||||
String diagnosticFlags = lines.stream()
|
||||
.filter(MessageLine::isDiagnosticFlags)
|
||||
.map(MessageLine::diagnosticFlags)
|
||||
.flatMap(Stream::of)
|
||||
.map(s -> s.replace('-', '_'))
|
||||
.map(s -> s.toUpperCase(Locale.ROOT))
|
||||
.collect(Collectors.joining(", "));
|
||||
String factoryName = factoryName(key);
|
||||
if (msgInfo.getTypes().isEmpty()) {
|
||||
//generate field
|
||||
String factoryField;
|
||||
if (lintCategory == null) {
|
||||
factoryField = StubKind.FACTORY_FIELD.format(k.keyClazz, factoryName,
|
||||
diagnosticFlags.isEmpty() ?
|
||||
StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() :
|
||||
StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags),
|
||||
"\"" + keyParts[0] + "\"",
|
||||
"\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
|
||||
javadoc);
|
||||
} else {
|
||||
factoryField = StubKind.FACTORY_FIELD_LINT.format(k.keyClazz, factoryName,
|
||||
diagnosticFlags.isEmpty() ?
|
||||
StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() :
|
||||
StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags),
|
||||
StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""),
|
||||
"\"" + keyParts[0] + "\"",
|
||||
"\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
|
||||
@ -287,11 +303,17 @@ public class ClassGenerator {
|
||||
String methodBody;
|
||||
if (lintCategory == null) {
|
||||
methodBody = StubKind.FACTORY_METHOD_BODY.format(k.keyClazz,
|
||||
diagnosticFlags.isEmpty() ?
|
||||
StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() :
|
||||
StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags),
|
||||
"\"" + keyParts[0] + "\"",
|
||||
"\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
|
||||
argNames.stream().collect(Collectors.joining(", ")));
|
||||
} else {
|
||||
methodBody = StubKind.FACTORY_METHOD_BODY_LINT.format(k.keyClazz,
|
||||
diagnosticFlags.isEmpty() ?
|
||||
StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() :
|
||||
StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags),
|
||||
StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""),
|
||||
"\"" + keyParts[0] + "\"",
|
||||
"\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
|
||||
|
||||
@ -32,7 +32,8 @@ import java.util.List;
|
||||
* A message within the message file.
|
||||
* A message is a series of lines containing a "name=value" property,
|
||||
* optionally preceded by a comment describing the use of placeholders
|
||||
* such as {0}, {1}, etc within the property value.
|
||||
* such as {0}, {1}, etc within the property value, a lint category,
|
||||
* and/or a list of diagnostic flags.
|
||||
*/
|
||||
public final class Message {
|
||||
final MessageLine firstLine;
|
||||
@ -49,7 +50,7 @@ public final class Message {
|
||||
public MessageInfo getMessageInfo() {
|
||||
if (messageInfo == null) {
|
||||
MessageLine l = firstLine.prev;
|
||||
if (l != null && l.isLint()) {
|
||||
while (l != null && (l.isLint() || l.isDiagnosticFlags())) {
|
||||
l = l.prev;
|
||||
}
|
||||
if (l != null && l.isInfo())
|
||||
@ -74,7 +75,7 @@ public final class Message {
|
||||
while (l.text.isEmpty())
|
||||
l = l.next;
|
||||
} else {
|
||||
if (l.prev != null && (l.prev.isInfo() || l.prev.isLint()))
|
||||
while (l.prev != null && (l.prev.isInfo() || l.prev.isLint() || l.prev.isDiagnosticFlags()))
|
||||
l = l.prev;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
package propertiesparser.parser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -39,6 +40,7 @@ public class MessageLine {
|
||||
static final Pattern infoPattern = Pattern.compile(String.format("# ([0-9]+: %s, )*[0-9]+: %s",
|
||||
typePattern.pattern(), typePattern.pattern()));
|
||||
static final Pattern lintPattern = Pattern.compile("# lint: ([a-z\\-]+)");
|
||||
static final Pattern diagnosticFlagsPattern = Pattern.compile("# flags: ([a-z\\-]+(, ([a-z\\-]+))*)");
|
||||
|
||||
public String text;
|
||||
MessageLine prev;
|
||||
@ -69,6 +71,19 @@ public class MessageLine {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDiagnosticFlags() {
|
||||
return diagnosticFlagsPattern.matcher(text).matches();
|
||||
}
|
||||
|
||||
public String[] diagnosticFlags() {
|
||||
Matcher matcher = diagnosticFlagsPattern.matcher(text);
|
||||
if (matcher.matches()) {
|
||||
return matcher.group(1).split(", ", -1);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasContinuation() {
|
||||
return (next != null) && text.endsWith("\\");
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ toplevel.decl=\
|
||||
package {0};\n\
|
||||
\n\
|
||||
{1}\n\
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;\n\
|
||||
import com.sun.tools.javac.util.JCDiagnostic.Error;\n\
|
||||
import com.sun.tools.javac.util.JCDiagnostic.Warning;\n\
|
||||
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;\n\
|
||||
@ -34,6 +35,10 @@ toplevel.decl=\
|
||||
import com.sun.tools.javac.util.JCDiagnostic.Fragment;\n\
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;\n\
|
||||
\n\
|
||||
import java.util.EnumSet;\n\
|
||||
\n\
|
||||
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;\n\
|
||||
\n\
|
||||
public class {2} '{'\n\
|
||||
{3}\n\
|
||||
'}'\n
|
||||
@ -58,22 +63,22 @@ factory.decl.method.arg=\
|
||||
arg{0}
|
||||
|
||||
factory.decl.method.body=\
|
||||
return new {0}({1}, {2}, {3});
|
||||
return new {0}({1}, {2}, {3}, {4});
|
||||
|
||||
factory.decl.method.body.lint=\
|
||||
return new {0}({1}, {2}, {3}, {4});
|
||||
return new {0}({1}, {2}, {3}, {4}, {5});
|
||||
|
||||
factory.decl.field=\
|
||||
/**\n\
|
||||
' '* {4}\n\
|
||||
' '*/\n\
|
||||
public static final {0} {1} = new {0}({2}, {3});
|
||||
public static final {0} {1} = new {0}({2}, {3}, {4});
|
||||
|
||||
factory.decl.field.lint=\
|
||||
/**\n\
|
||||
' '* {5}\n\
|
||||
' '*/\n\
|
||||
public static final {0} {1} = new {0}({2}, {3}, {4});
|
||||
public static final {0} {1} = new {0}({2}, {3}, {4}, {5});
|
||||
|
||||
wildcards.extends=\
|
||||
{0}<? extends {1}>
|
||||
@ -84,3 +89,9 @@ suppress.warnings=\
|
||||
lint.category=\
|
||||
LintCategory.get({0}).get()
|
||||
|
||||
diagnostic.flags.empty=\
|
||||
EnumSet.noneOf(DiagnosticFlag.class)
|
||||
|
||||
diagnostic.flags.non-empty=\
|
||||
EnumSet.of({0})
|
||||
|
||||
|
||||
@ -272,8 +272,6 @@ public class JavacTaskPool {
|
||||
((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear();
|
||||
Types.instance(this).newRound();
|
||||
Check.instance(this).newRound();
|
||||
Check.instance(this).clear(); //clear mandatory warning handlers
|
||||
Preview.instance(this).clear(); //clear mandatory warning handlers
|
||||
Modules.instance(this).newRound();
|
||||
Annotate.instance(this).newRound();
|
||||
CompileStates.instance(this).clear();
|
||||
|
||||
@ -40,7 +40,6 @@ import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.Warning;
|
||||
import com.sun.tools.javac.util.Log;
|
||||
import com.sun.tools.javac.util.MandatoryWarningHandler;
|
||||
import com.sun.tools.javac.util.Names;
|
||||
import com.sun.tools.javac.util.Options;
|
||||
|
||||
@ -71,9 +70,6 @@ public class Preview {
|
||||
/** flag: is the "preview" lint category enabled? */
|
||||
private final boolean verbose;
|
||||
|
||||
/** the diag handler to manage preview feature usage diagnostics */
|
||||
private final MandatoryWarningHandler previewHandler;
|
||||
|
||||
/** test flag: should all features be considered as preview features? */
|
||||
private final boolean forcePreview;
|
||||
|
||||
@ -105,7 +101,6 @@ public class Preview {
|
||||
log = Log.instance(context);
|
||||
source = Source.instance(context);
|
||||
verbose = Lint.instance(context).isEnabled(LintCategory.PREVIEW);
|
||||
previewHandler = new MandatoryWarningHandler(log, source, verbose, true, LintCategory.PREVIEW);
|
||||
forcePreview = options.isSet("forcePreview");
|
||||
majorVersionToSource = initMajorVersionToSourceMap();
|
||||
}
|
||||
@ -176,7 +171,8 @@ public class Preview {
|
||||
Assert.check(isEnabled());
|
||||
Assert.check(isPreview(feature));
|
||||
markUsesPreview(pos);
|
||||
previewHandler.report(pos, feature.isPlural() ?
|
||||
log.mandatoryWarning(pos,
|
||||
feature.isPlural() ?
|
||||
LintWarnings.PreviewFeatureUsePlural(feature.nameFragment()) :
|
||||
LintWarnings.PreviewFeatureUse(feature.nameFragment()));
|
||||
}
|
||||
@ -203,10 +199,6 @@ public class Preview {
|
||||
sourcesWithPreviewFeatures.add(log.currentSourceFile());
|
||||
}
|
||||
|
||||
public void reportPreviewWarning(DiagnosticPosition pos, LintWarning warnKey) {
|
||||
previewHandler.report(pos, warnKey);
|
||||
}
|
||||
|
||||
public boolean usesPreview(JavaFileObject file) {
|
||||
return sourcesWithPreviewFeatures.contains(file);
|
||||
}
|
||||
@ -269,25 +261,13 @@ public class Preview {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report any deferred diagnostics.
|
||||
*/
|
||||
public void reportDeferredDiagnostics() {
|
||||
previewHandler.reportDeferredDiagnostic();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
previewHandler.clear();
|
||||
}
|
||||
|
||||
public void checkSourceLevel(DiagnosticPosition pos, Feature feature) {
|
||||
if (isPreview(feature) && !isEnabled()) {
|
||||
//preview feature without --preview flag, error
|
||||
log.error(JCDiagnostic.DiagnosticFlag.SOURCE_LEVEL, pos, disabledError(feature));
|
||||
log.error(pos, disabledError(feature));
|
||||
} else {
|
||||
if (!feature.allowedInSource(source)) {
|
||||
log.error(JCDiagnostic.DiagnosticFlag.SOURCE_LEVEL, pos,
|
||||
feature.error(source.name));
|
||||
log.error(pos, feature.error(source.name));
|
||||
}
|
||||
if (isEnabled() && isPreview(feature)) {
|
||||
warnPreview(pos, feature);
|
||||
|
||||
@ -79,7 +79,6 @@ import static com.sun.tools.javac.code.Kinds.Kind.*;
|
||||
import static com.sun.tools.javac.code.TypeTag.*;
|
||||
import static com.sun.tools.javac.code.TypeTag.WILDCARD;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
||||
|
||||
/** This is the main context-dependent analysis phase in GJC. It
|
||||
* encompasses name resolution, type checking and constant folding as
|
||||
@ -4146,8 +4145,7 @@ public class Attr extends JCTree.Visitor {
|
||||
!exprtype.isErroneous() && !clazztype.isErroneous() &&
|
||||
tree.pattern.getTag() != RECORDPATTERN) {
|
||||
if (!allowUnconditionalPatternsInstanceOf) {
|
||||
log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(),
|
||||
Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.error(this.sourceName));
|
||||
log.error(tree.pos(), Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.error(this.sourceName));
|
||||
}
|
||||
}
|
||||
typeTree = TreeInfo.primaryPatternTypeTree((JCPattern) tree.pattern);
|
||||
@ -4167,8 +4165,7 @@ public class Attr extends JCTree.Visitor {
|
||||
if (allowReifiableTypesInInstanceof) {
|
||||
valid = checkCastablePattern(tree.expr.pos(), exprtype, clazztype);
|
||||
} else {
|
||||
log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(),
|
||||
Feature.REIFIABLE_TYPES_INSTANCEOF.error(this.sourceName));
|
||||
log.error(tree.pos(), Feature.REIFIABLE_TYPES_INSTANCEOF.error(this.sourceName));
|
||||
allowReifiableTypesInInstanceof = true;
|
||||
}
|
||||
if (!valid) {
|
||||
|
||||
@ -164,18 +164,6 @@ public class Check {
|
||||
profile = Profile.instance(context);
|
||||
preview = Preview.instance(context);
|
||||
|
||||
boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
|
||||
boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL);
|
||||
boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
|
||||
boolean enforceMandatoryWarnings = true;
|
||||
|
||||
deprecationHandler = new MandatoryWarningHandler(log, null, verboseDeprecated,
|
||||
enforceMandatoryWarnings, LintCategory.DEPRECATION, "deprecated");
|
||||
removalHandler = new MandatoryWarningHandler(log, null, verboseRemoval,
|
||||
enforceMandatoryWarnings, LintCategory.REMOVAL);
|
||||
uncheckedHandler = new MandatoryWarningHandler(log, null, verboseUnchecked,
|
||||
enforceMandatoryWarnings, LintCategory.UNCHECKED);
|
||||
|
||||
deferredLintHandler = DeferredLintHandler.instance(context);
|
||||
|
||||
allowModules = Feature.MODULES.allowedInSource(source);
|
||||
@ -192,18 +180,6 @@ public class Check {
|
||||
*/
|
||||
private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
|
||||
|
||||
/** A handler for messages about deprecated usage.
|
||||
*/
|
||||
private MandatoryWarningHandler deprecationHandler;
|
||||
|
||||
/** A handler for messages about deprecated-for-removal usage.
|
||||
*/
|
||||
private MandatoryWarningHandler removalHandler;
|
||||
|
||||
/** A handler for messages about unchecked or unsafe usage.
|
||||
*/
|
||||
private MandatoryWarningHandler uncheckedHandler;
|
||||
|
||||
/** A handler for deferred lint warnings.
|
||||
*/
|
||||
private DeferredLintHandler deferredLintHandler;
|
||||
@ -253,21 +229,24 @@ public class Check {
|
||||
* @param sym The deprecated symbol.
|
||||
*/
|
||||
void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
|
||||
LintWarning warningKey = null;
|
||||
if (sym.isDeprecatedForRemoval()) {
|
||||
if (!lint.isSuppressed(LintCategory.REMOVAL)) {
|
||||
if (sym.kind == MDL) {
|
||||
removalHandler.report(pos, LintWarnings.HasBeenDeprecatedForRemovalModule(sym));
|
||||
warningKey = LintWarnings.HasBeenDeprecatedForRemovalModule(sym);
|
||||
} else {
|
||||
removalHandler.report(pos, LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location()));
|
||||
warningKey = LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location());
|
||||
}
|
||||
}
|
||||
} else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
|
||||
if (sym.kind == MDL) {
|
||||
deprecationHandler.report(pos, LintWarnings.HasBeenDeprecatedModule(sym));
|
||||
warningKey = LintWarnings.HasBeenDeprecatedModule(sym);
|
||||
} else {
|
||||
deprecationHandler.report(pos, LintWarnings.HasBeenDeprecated(sym, sym.location()));
|
||||
warningKey = LintWarnings.HasBeenDeprecated(sym, sym.location());
|
||||
}
|
||||
}
|
||||
if (warningKey != null)
|
||||
log.mandatoryWarning(pos, warningKey);
|
||||
}
|
||||
|
||||
/** Log a preview warning.
|
||||
@ -276,7 +255,7 @@ public class Check {
|
||||
*/
|
||||
public void warnPreviewAPI(DiagnosticPosition pos, LintWarning warnKey) {
|
||||
if (!importSuppression && !lint.isSuppressed(LintCategory.PREVIEW))
|
||||
preview.reportPreviewWarning(pos, warnKey);
|
||||
log.mandatoryWarning(pos, warnKey);
|
||||
}
|
||||
|
||||
/** Log a preview warning.
|
||||
@ -293,25 +272,15 @@ public class Check {
|
||||
*/
|
||||
public void warnUnchecked(DiagnosticPosition pos, LintWarning warnKey) {
|
||||
if (!lint.isSuppressed(LintCategory.UNCHECKED))
|
||||
uncheckedHandler.report(pos, warnKey);
|
||||
log.mandatoryWarning(pos, warnKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report any deferred diagnostics.
|
||||
*/
|
||||
public void reportDeferredDiagnostics() {
|
||||
deprecationHandler.reportDeferredDiagnostic();
|
||||
removalHandler.reportDeferredDiagnostic();
|
||||
uncheckedHandler.reportDeferredDiagnostic();
|
||||
}
|
||||
|
||||
|
||||
/** Report a failure to complete a class.
|
||||
* @param pos Position to be used for error reporting.
|
||||
* @param ex The failure to report.
|
||||
*/
|
||||
public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
|
||||
log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, Errors.CantAccess(ex.sym, ex.getDetailValue()));
|
||||
log.error(DiagnosticFlag.NON_DEFERRABLE, pos, Errors.CantAccess(ex.sym, ex.getDetailValue()));
|
||||
return syms.errType;
|
||||
}
|
||||
|
||||
@ -474,12 +443,6 @@ public class Check {
|
||||
localClassNameIndexes.clear();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
deprecationHandler.clear();
|
||||
removalHandler.clear();
|
||||
uncheckedHandler.clear();
|
||||
}
|
||||
|
||||
public void putCompiled(ClassSymbol csym) {
|
||||
compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym);
|
||||
}
|
||||
|
||||
@ -28,11 +28,12 @@ package com.sun.tools.javac.launcher;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
import com.sun.source.util.TaskListener;
|
||||
import com.sun.tools.javac.api.JavacTool;
|
||||
import com.sun.tools.javac.code.Preview;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.resources.LauncherProperties.Errors;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.Context.Factory;
|
||||
import com.sun.tools.javac.util.Log;
|
||||
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
@ -120,8 +121,11 @@ final class MemoryContext {
|
||||
}
|
||||
var opts = options.forProgramCompilation();
|
||||
var context = new Context();
|
||||
MemoryPreview.registerInstance(context);
|
||||
var task = compiler.getTask(out, memoryFileManager, null, opts, null, units, context);
|
||||
|
||||
// This suppresses diagnostics like "Note: Recompile with -Xlint:preview for details."
|
||||
Log.instance(context).suppressAggregatedWarningNotes(LintCategory.PREVIEW);
|
||||
|
||||
var ok = task.call();
|
||||
if (!ok) {
|
||||
throw new Fault(Errors.CompilationFailed);
|
||||
@ -269,19 +273,4 @@ final class MemoryContext {
|
||||
controller.enableNativeAccess(module);
|
||||
}
|
||||
}
|
||||
|
||||
static class MemoryPreview extends Preview {
|
||||
static void registerInstance(Context context) {
|
||||
context.put(previewKey, (Factory<Preview>)MemoryPreview::new);
|
||||
}
|
||||
|
||||
MemoryPreview(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportDeferredDiagnostics() {
|
||||
// suppress diagnostics like "Note: Recompile with -Xlint:preview for details."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,10 +55,10 @@ import javax.tools.StandardLocation;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
import com.sun.tools.javac.api.MultiTaskListener;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.code.Source.Feature;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.CompletionFailure;
|
||||
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||
import com.sun.tools.javac.comp.*;
|
||||
import com.sun.tools.javac.comp.CompileStates.CompileState;
|
||||
@ -85,10 +85,6 @@ import com.sun.tools.javac.util.Log.WriterKind;
|
||||
|
||||
import static com.sun.tools.javac.code.Kinds.Kind.*;
|
||||
|
||||
import com.sun.tools.javac.code.Lint;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Notes;
|
||||
@ -274,10 +270,6 @@ public class JavaCompiler {
|
||||
*/
|
||||
protected Source source;
|
||||
|
||||
/** The preview language version.
|
||||
*/
|
||||
protected Preview preview;
|
||||
|
||||
/** The module for code generation.
|
||||
*/
|
||||
protected Gen gen;
|
||||
@ -413,7 +405,6 @@ public class JavaCompiler {
|
||||
log.error(Errors.CantAccess(ex.sym, ex.getDetailValue()));
|
||||
}
|
||||
source = Source.instance(context);
|
||||
preview = Preview.instance(context);
|
||||
attr = Attr.instance(context);
|
||||
analyzer = Analyzer.instance(context);
|
||||
chk = Check.instance(context);
|
||||
@ -1852,8 +1843,7 @@ public class JavaCompiler {
|
||||
else
|
||||
log.warning(Warnings.ProcUseProcOrImplicit);
|
||||
}
|
||||
chk.reportDeferredDiagnostics();
|
||||
preview.reportDeferredDiagnostics();
|
||||
log.reportOutstandingNotes();
|
||||
if (log.compressedOutput) {
|
||||
log.mandatoryNote(null, Notes.CompressedDiags);
|
||||
}
|
||||
|
||||
@ -181,10 +181,10 @@ public class JavaTokenizer extends UnicodeReader {
|
||||
protected void checkSourceLevel(int pos, Feature feature) {
|
||||
if (preview.isPreview(feature) && !preview.isEnabled()) {
|
||||
//preview feature without --preview flag, error
|
||||
lexError(DiagnosticFlag.SOURCE_LEVEL, pos, preview.disabledError(feature));
|
||||
lexError(pos, preview.disabledError(feature));
|
||||
} else if (!feature.allowedInSource(source)) {
|
||||
//incompatible source level, error
|
||||
lexError(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
|
||||
lexError(pos, feature.error(source.name));
|
||||
} else if (preview.isPreview(feature)) {
|
||||
//use of preview feature, warn
|
||||
preview.warnPreview(pos, feature);
|
||||
@ -199,20 +199,7 @@ public class JavaTokenizer extends UnicodeReader {
|
||||
*/
|
||||
protected void lexError(int pos, JCDiagnostic.Error key) {
|
||||
log.error(pos, key);
|
||||
tk = TokenKind.ERROR;
|
||||
errPos = pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an error at the given position using the provided arguments.
|
||||
*
|
||||
* @param flags diagnostic flags.
|
||||
* @param pos position in input buffer.
|
||||
* @param key error key to report.
|
||||
*/
|
||||
protected void lexError(DiagnosticFlag flags, int pos, JCDiagnostic.Error key) {
|
||||
log.error(flags, pos, key);
|
||||
if (flags != DiagnosticFlag.SOURCE_LEVEL) {
|
||||
if (!key.hasFlag(DiagnosticFlag.SOURCE_LEVEL)) {
|
||||
tk = TokenKind.ERROR;
|
||||
}
|
||||
errPos = pos;
|
||||
|
||||
@ -5611,10 +5611,10 @@ public class JavacParser implements Parser {
|
||||
protected void checkSourceLevel(int pos, Feature feature) {
|
||||
if (preview.isPreview(feature) && !preview.isEnabled()) {
|
||||
//preview feature without --preview flag, error
|
||||
log.error(DiagnosticFlag.SOURCE_LEVEL, pos, preview.disabledError(feature));
|
||||
log.error(pos, preview.disabledError(feature));
|
||||
} else if (!feature.allowedInSource(source)) {
|
||||
//incompatible source level, error
|
||||
log.error(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
|
||||
log.error(pos, feature.error(source.name));
|
||||
} else if (preview.isPreview(feature)) {
|
||||
//use of preview feature, warn
|
||||
preview.warnPreview(pos, feature);
|
||||
|
||||
@ -1923,16 +1923,19 @@ compiler.warn.incubating.modules=\
|
||||
|
||||
# 0: symbol, 1: symbol
|
||||
# lint: deprecation
|
||||
# flags: aggregate
|
||||
compiler.warn.has.been.deprecated=\
|
||||
{0} in {1} has been deprecated
|
||||
|
||||
# 0: symbol, 1: symbol
|
||||
# lint: removal
|
||||
# flags: aggregate
|
||||
compiler.warn.has.been.deprecated.for.removal=\
|
||||
{0} in {1} has been deprecated and marked for removal
|
||||
|
||||
# 0: symbol
|
||||
# lint: preview
|
||||
# flags: aggregate
|
||||
compiler.warn.is.preview=\
|
||||
{0} is a preview API and may be removed in a future release.
|
||||
|
||||
@ -1943,6 +1946,7 @@ compiler.err.is.preview=\
|
||||
|
||||
# 0: symbol
|
||||
# lint: preview
|
||||
# flags: aggregate
|
||||
compiler.warn.is.preview.reflective=\
|
||||
{0} is a reflective preview API and may be removed in a future release.
|
||||
|
||||
@ -1954,11 +1958,13 @@ compiler.warn.restricted.method=\
|
||||
|
||||
# 0: symbol
|
||||
# lint: deprecation
|
||||
# flags: aggregate
|
||||
compiler.warn.has.been.deprecated.module=\
|
||||
module {0} has been deprecated
|
||||
|
||||
# 0: symbol
|
||||
# lint: removal
|
||||
# flags: aggregate
|
||||
compiler.warn.has.been.deprecated.for.removal.module=\
|
||||
module {0} has been deprecated and marked for removal
|
||||
|
||||
@ -2357,11 +2363,13 @@ compiler.warn.unchecked.assign=\
|
||||
|
||||
# 0: symbol, 1: type
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.unchecked.assign.to.var=\
|
||||
unchecked assignment to variable {0} as member of raw type {1}
|
||||
|
||||
# 0: symbol, 1: type
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.unchecked.call.mbr.of.raw.type=\
|
||||
unchecked call to {0} as a member of the raw type {1}
|
||||
|
||||
@ -2371,6 +2379,7 @@ compiler.warn.unchecked.cast.to.type=\
|
||||
|
||||
# 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.unchecked.meth.invocation.applied=\
|
||||
unchecked method invocation: {0} {1} in {4} {5} is applied to given types\n\
|
||||
required: {2}\n\
|
||||
@ -2378,11 +2387,13 @@ compiler.warn.unchecked.meth.invocation.applied=\
|
||||
|
||||
# 0: type
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.unchecked.generic.array.creation=\
|
||||
unchecked generic array creation for varargs parameter of type {0}
|
||||
|
||||
# 0: type
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.unchecked.varargs.non.reifiable.type=\
|
||||
Possible heap pollution from parameterized vararg type {0}
|
||||
|
||||
@ -2781,6 +2792,7 @@ compiler.misc.prob.found.req=\
|
||||
|
||||
# 0: message segment, 1: type, 2: type
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.prob.found.req=\
|
||||
{0}\n\
|
||||
required: {2}\n\
|
||||
@ -3177,12 +3189,14 @@ compiler.err.override.incompatible.ret=\
|
||||
|
||||
# 0: message segment, 1: type, 2: type
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.override.unchecked.ret=\
|
||||
{0}\n\
|
||||
return type requires unchecked conversion from {1} to {2}
|
||||
|
||||
# 0: message segment, 1: type
|
||||
# lint: unchecked
|
||||
# flags: aggregate
|
||||
compiler.warn.override.unchecked.thrown=\
|
||||
{0}\n\
|
||||
overridden method does not throw {1}
|
||||
@ -3246,11 +3260,13 @@ compiler.misc.inapplicable.method=\
|
||||
########################################
|
||||
|
||||
# 0: message segment (feature), 1: string (found version), 2: string (expected version)
|
||||
# flags: source-level
|
||||
compiler.err.feature.not.supported.in.source=\
|
||||
{0} is not supported in -source {1}\n\
|
||||
(use -source {2} or higher to enable {0})
|
||||
|
||||
# 0: message segment (feature), 1: string (found version), 2: string (expected version)
|
||||
# flags: source-level
|
||||
compiler.err.feature.not.supported.in.source.plural=\
|
||||
{0} are not supported in -source {1}\n\
|
||||
(use -source {2} or higher to enable {0})
|
||||
@ -3266,11 +3282,13 @@ compiler.misc.feature.not.supported.in.source.plural=\
|
||||
(use -source {2} or higher to enable {0})
|
||||
|
||||
# 0: message segment (feature)
|
||||
# flags: source-level
|
||||
compiler.err.preview.feature.disabled=\
|
||||
{0} is a preview feature and is disabled by default.\n\
|
||||
(use --enable-preview to enable {0})
|
||||
|
||||
# 0: message segment (feature)
|
||||
# flags: source-level
|
||||
compiler.err.preview.feature.disabled.plural=\
|
||||
{0} are a preview feature and are disabled by default.\n\
|
||||
(use --enable-preview to enable {0})
|
||||
@ -3282,11 +3300,13 @@ compiler.err.preview.feature.disabled.classfile=\
|
||||
|
||||
# 0: message segment (feature)
|
||||
# lint: preview
|
||||
# flags: aggregate
|
||||
compiler.warn.preview.feature.use=\
|
||||
{0} is a preview feature and may be removed in a future release.
|
||||
|
||||
# 0: message segment (feature)
|
||||
# lint: preview
|
||||
# flags: aggregate
|
||||
compiler.warn.preview.feature.use.plural=\
|
||||
{0} are a preview feature and may be removed in a future release.
|
||||
|
||||
@ -4249,6 +4269,7 @@ compiler.err.incorrect.number.of.nested.patterns=\
|
||||
|
||||
# 0: kind name, 1: symbol
|
||||
# lint: preview
|
||||
# flags: aggregate
|
||||
compiler.warn.declared.using.preview=\
|
||||
{0} {1} is declared using a preview feature, which may be removed in a future release.
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
package com.sun.tools.javac.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.Locale;
|
||||
@ -237,7 +238,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
*/
|
||||
public JCDiagnostic create(
|
||||
DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
|
||||
return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args));
|
||||
return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, null, prefix, key, args));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -252,7 +253,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
*/
|
||||
public JCDiagnostic create(
|
||||
DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, UnaryOperator<JCDiagnostic> rewriter, Object... args) {
|
||||
return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args), rewriter);
|
||||
return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, null, prefix, key, args), rewriter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,7 +280,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
*/
|
||||
public JCDiagnostic create(DiagnosticType kind,
|
||||
LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
|
||||
return create(flags, source, pos, DiagnosticInfo.of(kind, lc, prefix, key, args));
|
||||
return create(flags, source, pos, DiagnosticInfo.of(kind, null, lc, prefix, key, args));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -303,7 +304,8 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
//replace all nested FragmentKey with full-blown JCDiagnostic objects
|
||||
LintCategory category = diagnosticInfo instanceof LintWarning lintWarning ?
|
||||
lintWarning.category : null;
|
||||
return DiagnosticInfo.of(diagnosticInfo.type, category, diagnosticInfo.prefix, diagnosticInfo.code,
|
||||
return DiagnosticInfo.of(diagnosticInfo.type, diagnosticInfo.flags,
|
||||
category, diagnosticInfo.prefix, diagnosticInfo.code,
|
||||
Stream.of(diagnosticInfo.args).map(o -> {
|
||||
return (o instanceof Fragment frag) ?
|
||||
fragment(frag) : o;
|
||||
@ -314,28 +316,28 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* Create a new error key.
|
||||
*/
|
||||
public Error errorKey(String code, Object... args) {
|
||||
return (Error)DiagnosticInfo.of(ERROR, prefix, code, args);
|
||||
return (Error)DiagnosticInfo.of(ERROR, null, prefix, code, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new warning key.
|
||||
*/
|
||||
Warning warningKey(LintCategory lintCategory, String code, Object... args) {
|
||||
return (Warning)DiagnosticInfo.of(WARNING, lintCategory, prefix, code, args);
|
||||
return (Warning)DiagnosticInfo.of(WARNING, null, lintCategory, prefix, code, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new note key.
|
||||
*/
|
||||
public Note noteKey(String code, Object... args) {
|
||||
return (Note)DiagnosticInfo.of(NOTE, prefix, code, args);
|
||||
return (Note)DiagnosticInfo.of(NOTE, null, prefix, code, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new fragment key.
|
||||
*/
|
||||
Fragment fragmentKey(String code, Object... args) {
|
||||
return (Fragment)DiagnosticInfo.of(FRAGMENT, prefix, code, args);
|
||||
return (Fragment)DiagnosticInfo.of(FRAGMENT, null, prefix, code, args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,6 +353,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
public static JCDiagnostic fragment(String key, Object... args) {
|
||||
return new JCDiagnostic(getFragmentFormatter(),
|
||||
DiagnosticInfo.of(FRAGMENT,
|
||||
null,
|
||||
null,
|
||||
"compiler",
|
||||
key,
|
||||
@ -447,6 +450,9 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
RECOVERABLE,
|
||||
NON_DEFERRABLE,
|
||||
COMPRESSED,
|
||||
/** Flags mandatory warnings that should pass through a mandatory warning aggregator.
|
||||
*/
|
||||
AGGREGATE,
|
||||
/** Flag for diagnostics that were reported through API methods.
|
||||
*/
|
||||
API,
|
||||
@ -503,6 +509,9 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
/** The diagnostic kind (i.e. error). */
|
||||
DiagnosticType type;
|
||||
|
||||
/** A set of diagnostic flags to be automatically added to newly created JCDiagnostics. */
|
||||
Set<DiagnosticFlag> flags;
|
||||
|
||||
/** The diagnostic prefix (i.e. 'javac'); used to compute full resource key. */
|
||||
String prefix;
|
||||
|
||||
@ -513,8 +522,9 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
/** The diagnostic arguments. */
|
||||
Object[] args;
|
||||
|
||||
private DiagnosticInfo(DiagnosticType type, String prefix, String code, Object... args) {
|
||||
private DiagnosticInfo(DiagnosticType type, Set<DiagnosticFlag> flags, String prefix, String code, Object... args) {
|
||||
this.type = type;
|
||||
this.flags = flags != null ? flags : EnumSet.noneOf(DiagnosticFlag.class);
|
||||
this.prefix = prefix;
|
||||
this.code = code;
|
||||
this.args = args;
|
||||
@ -530,22 +540,24 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
/**
|
||||
* Static factory method; build a custom diagnostic key using given kind, prefix, code and args.
|
||||
*/
|
||||
public static DiagnosticInfo of(DiagnosticType type, String prefix, String code, Object... args) {
|
||||
return of(type, null, prefix, code, args);
|
||||
public static DiagnosticInfo of(DiagnosticType type, Set<DiagnosticFlag> flags,
|
||||
String prefix, String code, Object... args) {
|
||||
return of(type, flags, null, prefix, code, args);
|
||||
}
|
||||
|
||||
public static DiagnosticInfo of(DiagnosticType type, LintCategory lc, String prefix, String code, Object... args) {
|
||||
public static DiagnosticInfo of(DiagnosticType type, Set<DiagnosticFlag> flags,
|
||||
LintCategory lc, String prefix, String code, Object... args) {
|
||||
switch (type) {
|
||||
case ERROR:
|
||||
return new Error(prefix, code, args);
|
||||
return new Error(flags, prefix, code, args);
|
||||
case WARNING:
|
||||
return lc == null ?
|
||||
new Warning(prefix, code, args) :
|
||||
new LintWarning(lc, prefix, code, args);
|
||||
new Warning(flags, prefix, code, args) :
|
||||
new LintWarning(flags, lc, prefix, code, args);
|
||||
case NOTE:
|
||||
return new Note(prefix, code, args);
|
||||
return new Note(flags, prefix, code, args);
|
||||
case FRAGMENT:
|
||||
return new Fragment(prefix, code, args);
|
||||
return new Fragment(flags, prefix, code, args);
|
||||
default:
|
||||
Assert.error("Wrong diagnostic type: " + type);
|
||||
return null;
|
||||
@ -569,14 +581,18 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
public void setArgs(Object[] args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public boolean hasFlag(DiagnosticFlag flag) {
|
||||
return flags.contains(flag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing error diagnostic keys.
|
||||
*/
|
||||
public static final class Error extends DiagnosticInfo {
|
||||
public Error(String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.ERROR, prefix, key, args);
|
||||
public Error(Set<DiagnosticFlag> flags, String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.ERROR, flags, prefix, key, args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -584,8 +600,8 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* Class representing warning diagnostic keys.
|
||||
*/
|
||||
public static sealed class Warning extends DiagnosticInfo {
|
||||
public Warning(String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.WARNING, prefix, key, args);
|
||||
public Warning(Set<DiagnosticFlag> flags, String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.WARNING, flags, prefix, key, args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -595,8 +611,8 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
public static final class LintWarning extends Warning {
|
||||
final LintCategory category;
|
||||
|
||||
public LintWarning(LintCategory category, String prefix, String key, Object... args) {
|
||||
super(prefix, key, args);
|
||||
public LintWarning(Set<DiagnosticFlag> flags, LintCategory category, String prefix, String key, Object... args) {
|
||||
super(flags, prefix, key, args);
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
@ -609,8 +625,8 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* Class representing note diagnostic keys.
|
||||
*/
|
||||
public static final class Note extends DiagnosticInfo {
|
||||
public Note(String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.NOTE, prefix, key, args);
|
||||
public Note(Set<DiagnosticFlag> flags, String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.NOTE, flags, prefix, key, args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,8 +634,8 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* Class representing fragment diagnostic keys.
|
||||
*/
|
||||
public static final class Fragment extends DiagnosticInfo {
|
||||
public Fragment(String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.FRAGMENT, prefix, key, args);
|
||||
public Fragment(Set<DiagnosticFlag> flags, String prefix, String key, Object... args) {
|
||||
super(DiagnosticType.FRAGMENT, flags, prefix, key, args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -664,6 +680,8 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
this.source = source;
|
||||
this.position = pos;
|
||||
this.rewriter = rewriter;
|
||||
|
||||
this.flags.addAll(diagnosticInfo.flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -30,6 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -41,15 +42,18 @@ import javax.tools.DiagnosticListener;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.api.DiagnosticFormatter;
|
||||
import com.sun.tools.javac.code.Lint;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.code.Source;
|
||||
import com.sun.tools.javac.main.Main;
|
||||
import com.sun.tools.javac.main.Option;
|
||||
import com.sun.tools.javac.tree.EndPosTable;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticInfo;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
|
||||
|
||||
import static com.sun.tools.javac.main.Option.*;
|
||||
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
|
||||
|
||||
/** A class for error logs. Reports errors and warnings, and
|
||||
* keeps track of error numbers and positions.
|
||||
@ -148,7 +152,7 @@ public class Log extends AbstractLog {
|
||||
}
|
||||
|
||||
private boolean deferrable(JCDiagnostic diag) {
|
||||
return !(diag.isFlagSet(DiagnosticFlag.NON_DEFERRABLE) && passOnNonDeferrable) && filter.test(diag);
|
||||
return !(diag.isFlagSet(NON_DEFERRABLE) && passOnNonDeferrable) && filter.test(diag);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -237,6 +241,16 @@ public class Log extends AbstractLog {
|
||||
*/
|
||||
private JavacMessages messages;
|
||||
|
||||
/**
|
||||
* The compilation context.
|
||||
*/
|
||||
private final Context context;
|
||||
|
||||
/**
|
||||
* The root {@link Lint} singleton.
|
||||
*/
|
||||
private Lint rootLint;
|
||||
|
||||
/**
|
||||
* Handler for initial dispatch of diagnostics.
|
||||
*/
|
||||
@ -334,6 +348,7 @@ public class Log extends AbstractLog {
|
||||
private Log(Context context, Map<WriterKind, PrintWriter> writers) {
|
||||
super(JCDiagnostic.Factory.instance(context));
|
||||
context.put(logKey, this);
|
||||
this.context = context;
|
||||
this.writers = writers;
|
||||
|
||||
@SuppressWarnings("unchecked") // FIXME
|
||||
@ -517,7 +532,7 @@ public class Log extends AbstractLog {
|
||||
if (!shouldReport(file, d.getIntPosition()))
|
||||
return false;
|
||||
|
||||
if (!d.isFlagSet(DiagnosticFlag.SOURCE_LEVEL))
|
||||
if (!d.isFlagSet(SOURCE_LEVEL))
|
||||
return true;
|
||||
|
||||
Pair<JavaFileObject, List<String>> coords = new Pair<>(file, getCode(d));
|
||||
@ -681,7 +696,48 @@ public class Log extends AbstractLog {
|
||||
@Override
|
||||
public void report(JCDiagnostic diagnostic) {
|
||||
diagnosticHandler.report(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain root Lint singleton lazily to avoid init loops
|
||||
private Lint rootLint() {
|
||||
if (rootLint == null)
|
||||
rootLint = Lint.instance(context);
|
||||
return rootLint;
|
||||
}
|
||||
|
||||
// Mandatory Warnings
|
||||
|
||||
private final EnumMap<LintCategory, WarningAggregator> aggregators = new EnumMap<>(LintCategory.class);
|
||||
|
||||
private final EnumSet<LintCategory> suppressedDeferredMandatory = EnumSet.noneOf(LintCategory.class);
|
||||
|
||||
/**
|
||||
* Suppress aggregated mandatory warning notes for the specified category.
|
||||
*/
|
||||
public void suppressAggregatedWarningNotes(LintCategory category) {
|
||||
suppressedDeferredMandatory.add(category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report any remaining unreported aggregated mandatory warning notes.
|
||||
*/
|
||||
public void reportOutstandingNotes() {
|
||||
aggregators.entrySet().stream()
|
||||
.filter(entry -> !suppressedDeferredMandatory.contains(entry.getKey()))
|
||||
.map(Map.Entry::getValue)
|
||||
.map(WarningAggregator::aggregationNotes)
|
||||
.flatMap(List::stream)
|
||||
.forEach(this::report);
|
||||
aggregators.clear();
|
||||
}
|
||||
|
||||
private WarningAggregator aggregatorFor(LintCategory lc) {
|
||||
return switch (lc) {
|
||||
case PREVIEW -> aggregators.computeIfAbsent(lc, c -> new WarningAggregator(this, Source.instance(context), c));
|
||||
case DEPRECATION -> aggregators.computeIfAbsent(lc, c -> new WarningAggregator(this, null, c, "deprecated"));
|
||||
default -> aggregators.computeIfAbsent(lc, c -> new WarningAggregator(this, null, c));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the state of this instance.
|
||||
@ -695,14 +751,19 @@ public class Log extends AbstractLog {
|
||||
nsuppressedwarns = 0;
|
||||
while (diagnosticHandler.prev != null)
|
||||
popDiagnosticHandler(diagnosticHandler);
|
||||
aggregators.clear();
|
||||
suppressedDeferredMandatory.clear();
|
||||
}
|
||||
|
||||
// DefaultDiagnosticHandler
|
||||
|
||||
/**
|
||||
* Common diagnostic handling.
|
||||
* The diagnostic is counted, and depending on the options and how many diagnostics have been
|
||||
* reported so far, the diagnostic may be handed off to writeDiagnostic.
|
||||
*/
|
||||
private class DefaultDiagnosticHandler extends DiagnosticHandler {
|
||||
|
||||
@Override
|
||||
public void report(JCDiagnostic diagnostic) {
|
||||
if (expectDiagKeys != null)
|
||||
@ -727,6 +788,16 @@ public class Log extends AbstractLog {
|
||||
break;
|
||||
|
||||
case WARNING:
|
||||
|
||||
// Apply the appropriate mandatory warning aggregator, if needed
|
||||
if (diagnostic.isFlagSet(AGGREGATE)) {
|
||||
LintCategory category = diagnostic.getLintCategory();
|
||||
boolean verbose = rootLint().isEnabled(category);
|
||||
if (!aggregatorFor(category).aggregate(diagnostic, verbose))
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit warning unless not mandatory and warnings are disabled
|
||||
if (emitWarnings || diagnostic.isMandatory()) {
|
||||
if (nwarnings < MaxWarnings) {
|
||||
writeDiagnostic(diagnostic);
|
||||
@ -738,8 +809,7 @@ public class Log extends AbstractLog {
|
||||
break;
|
||||
|
||||
case ERROR:
|
||||
if (diagnostic.isFlagSet(DiagnosticFlag.API) ||
|
||||
shouldReport(diagnostic)) {
|
||||
if (diagnostic.isFlagSet(API) || shouldReport(diagnostic)) {
|
||||
if (nerrors < MaxErrors) {
|
||||
writeDiagnostic(diagnostic);
|
||||
nerrors++;
|
||||
@ -749,7 +819,7 @@ public class Log extends AbstractLog {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (diagnostic.isFlagSet(JCDiagnostic.DiagnosticFlag.COMPRESSED)) {
|
||||
if (diagnostic.isFlagSet(COMPRESSED)) {
|
||||
compressedOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,11 +25,14 @@
|
||||
|
||||
package com.sun.tools.javac.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.code.Lint;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.code.Source;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
@ -39,16 +42,10 @@ import com.sun.tools.javac.util.JCDiagnostic.Warning;
|
||||
|
||||
|
||||
/**
|
||||
* A handler to process mandatory warnings, setting up a deferred diagnostic
|
||||
* An aggregator for warnings, setting up a deferred diagnostic
|
||||
* to be printed at the end of the compilation if some warnings get suppressed
|
||||
* because too many warnings have already been generated.
|
||||
*
|
||||
* <p>
|
||||
* Note that the SuppressWarnings annotation can be used to suppress warnings
|
||||
* about conditions that would otherwise merit a warning. Such processing
|
||||
* is done when the condition is detected, and in those cases, no call is
|
||||
* made on any API to generate a warning at all. In consequence, this handler only
|
||||
* Returns to handle those warnings that JLS says must be generated.
|
||||
* because the lint category is not enabled or too many warnings have already
|
||||
* been generated.
|
||||
*
|
||||
* <p>
|
||||
* All warnings must be in the same {@link LintCategory} provided to the constructor.
|
||||
@ -58,12 +55,11 @@ import com.sun.tools.javac.util.JCDiagnostic.Warning;
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class MandatoryWarningHandler {
|
||||
class WarningAggregator {
|
||||
|
||||
/**
|
||||
* The kinds of different deferred diagnostics that might be generated
|
||||
* if a mandatory warning is suppressed because too many warnings have
|
||||
* already been output.
|
||||
* if a warning is suppressed because too many warnings have already been output.
|
||||
*
|
||||
* The parameter is a fragment used to build an I18N message key for Log.
|
||||
*/
|
||||
@ -105,64 +101,50 @@ public class MandatoryWarningHandler {
|
||||
|
||||
|
||||
/**
|
||||
* Create a handler for mandatory warnings.
|
||||
* Create an aggregator for warnings.
|
||||
*
|
||||
* @param log The log on which to generate any diagnostics
|
||||
* @param source Associated source file, or null for none
|
||||
* @param verbose Specify whether or not detailed messages about
|
||||
* individual instances should be given, or whether an aggregate
|
||||
* message should be generated at the end of the compilation.
|
||||
* Typically set via -Xlint:option.
|
||||
* @param enforceMandatory
|
||||
* True if mandatory warnings and notes are being enforced.
|
||||
* @param lc The lint category for all warnings
|
||||
*/
|
||||
public MandatoryWarningHandler(Log log, Source source, boolean verbose, boolean enforceMandatory, LintCategory lc) {
|
||||
this(log, source, verbose, enforceMandatory, lc, null);
|
||||
public WarningAggregator(Log log, Source source, LintCategory lc) {
|
||||
this(log, source, lc, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a handler for mandatory warnings.
|
||||
* Create an aggregator for warnings.
|
||||
*
|
||||
* @param log The log on which to generate any diagnostics
|
||||
* @param source Associated source file, or null for none
|
||||
* @param verbose Specify whether or not detailed messages about
|
||||
* individual instances should be given, or whether an aggregate
|
||||
* message should be generated at the end of the compilation.
|
||||
* Typically set via -Xlint:option.
|
||||
* @param enforceMandatory
|
||||
* True if mandatory warnings and notes are being enforced.
|
||||
* @param lc The lint category for all warnings
|
||||
* @param prefix A common prefix for the set of message keys for the messages
|
||||
* that may be generated, or null to infer from the lint category.
|
||||
*/
|
||||
public MandatoryWarningHandler(Log log, Source source, boolean verbose, boolean enforceMandatory, LintCategory lc, String prefix) {
|
||||
public WarningAggregator(Log log, Source source, LintCategory lc, String prefix) {
|
||||
this.log = log;
|
||||
this.source = source;
|
||||
this.verbose = verbose;
|
||||
this.prefix = prefix != null ? prefix : lc.option;
|
||||
this.enforceMandatory = enforceMandatory;
|
||||
this.lintCategory = lc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a mandatory warning.
|
||||
* Aggregate a warning and determine whether to emit it.
|
||||
*
|
||||
* @param pos source code position
|
||||
* @param warnKey lint warning
|
||||
* @param diagnostic the warning
|
||||
* @param verbose whether the warning's lint category is enabled
|
||||
* @return true if diagnostic should be emitted, otherwise false
|
||||
*/
|
||||
public void report(DiagnosticPosition pos, LintWarning warnKey) {
|
||||
public boolean aggregate(JCDiagnostic diagnostic, boolean verbose) {
|
||||
Assert.check(diagnostic.getLintCategory() == lintCategory);
|
||||
JavaFileObject currentSource = log.currentSourceFile();
|
||||
Assert.check(warnKey.getLintCategory() == lintCategory);
|
||||
|
||||
if (verbose) {
|
||||
if (sourcesWithReportedWarnings == null)
|
||||
sourcesWithReportedWarnings = new HashSet<>();
|
||||
|
||||
if (log.nwarnings < log.MaxWarnings) {
|
||||
// generate message and remember the source file
|
||||
logMandatoryWarning(pos, warnKey);
|
||||
sourcesWithReportedWarnings.add(currentSource);
|
||||
anyWarningEmitted = true;
|
||||
return true;
|
||||
} else if (deferredDiagnosticKind == null) {
|
||||
// set up deferred message
|
||||
if (sourcesWithReportedWarnings.contains(currentSource)) {
|
||||
@ -194,30 +176,36 @@ public class MandatoryWarningHandler {
|
||||
deferredDiagnosticArg = null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report any diagnostic that might have been deferred by previous calls of report().
|
||||
* Build and return any accumulated aggregation notes.
|
||||
*/
|
||||
public void reportDeferredDiagnostic() {
|
||||
public List<JCDiagnostic> aggregationNotes() {
|
||||
List<JCDiagnostic> list = new ArrayList<>(2);
|
||||
if (deferredDiagnosticKind != null) {
|
||||
if (deferredDiagnosticArg == null) {
|
||||
if (source != null) {
|
||||
logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), source);
|
||||
addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), source);
|
||||
} else {
|
||||
logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix));
|
||||
addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix));
|
||||
}
|
||||
} else {
|
||||
if (source != null) {
|
||||
logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg, source);
|
||||
addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg, source);
|
||||
} else {
|
||||
logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg);
|
||||
addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!verbose)
|
||||
logMandatoryNote(deferredDiagnosticSource, prefix + ".recompile");
|
||||
if (!anyWarningEmitted)
|
||||
addNote(list, deferredDiagnosticSource, prefix + ".recompile");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void addNote(List<JCDiagnostic> list, JavaFileObject file, String msg, Object... args) {
|
||||
list.add(log.diags.mandatoryNote(log.getSource(file), new Note(null, "compiler", msg, args)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,12 +214,6 @@ public class MandatoryWarningHandler {
|
||||
private final Log log;
|
||||
private final Source source;
|
||||
|
||||
/**
|
||||
* Whether or not to report individual warnings, or simply to report a
|
||||
* single aggregate warning at the end of the compilation.
|
||||
*/
|
||||
private final boolean verbose;
|
||||
|
||||
/**
|
||||
* The common prefix for all I18N message keys generated by this handler.
|
||||
*/
|
||||
@ -268,9 +250,10 @@ public class MandatoryWarningHandler {
|
||||
private Object deferredDiagnosticArg;
|
||||
|
||||
/**
|
||||
* True if mandatory warnings and notes are being enforced.
|
||||
* Whether we have actually emitted a warning or just deferred everything.
|
||||
* In the latter case, the "recompile" notice is included in the summary.
|
||||
*/
|
||||
private final boolean enforceMandatory;
|
||||
private boolean anyWarningEmitted;
|
||||
|
||||
/**
|
||||
* A LintCategory to be included in point-of-use diagnostics to indicate
|
||||
@ -278,28 +261,6 @@ public class MandatoryWarningHandler {
|
||||
*/
|
||||
private final LintCategory lintCategory;
|
||||
|
||||
/**
|
||||
* Reports a mandatory warning to the log. If mandatory warnings
|
||||
* are not being enforced, treat this as an ordinary warning.
|
||||
*/
|
||||
private void logMandatoryWarning(DiagnosticPosition pos, LintWarning warnKey) {
|
||||
if (enforceMandatory)
|
||||
log.mandatoryWarning(pos, warnKey);
|
||||
else
|
||||
log.warning(pos, warnKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a mandatory note to the log. If mandatory notes are
|
||||
* not being enforced, treat this as an ordinary note.
|
||||
*/
|
||||
private void logMandatoryNote(JavaFileObject file, String msg, Object... args) {
|
||||
if (enforceMandatory)
|
||||
log.mandatoryNote(file, new Note("compiler", msg, args));
|
||||
else
|
||||
log.note(file, new Note("compiler", msg, args));
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
sourcesWithReportedWarnings = null;
|
||||
deferredDiagnosticKind = null;
|
||||
Loading…
x
Reference in New Issue
Block a user