8348611: Eliminate DeferredLintHandler and emit warnings after attribution

8224228: No way to locally suppress lint warnings in parser/tokenizer or preview features
8353758: Missing calls to Log.useSource() in JavacTrees

Reviewed-by: mcimadamore, vromero, jlahoda
This commit is contained in:
Archie Cobbs 2025-08-20 15:04:48 +00:00
parent 5ca8d7c2a7
commit 3e60ab51fe
56 changed files with 1344 additions and 948 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -412,6 +412,7 @@ public class JavacTaskImpl extends BasicJavacTask {
f.run(compiler.todo, classes);
}
} finally {
compiler.log.reportOutstandingWarnings();
compiler.log.flush();
}
return results;
@ -483,8 +484,10 @@ public class JavacTaskImpl extends BasicJavacTask {
}
}
finally {
if (compiler != null)
if (compiler != null) {
compiler.log.reportOutstandingWarnings();
compiler.log.flush();
}
}
return results;
}

View File

@ -55,6 +55,7 @@ import com.sun.source.util.TaskEvent.Kind;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
@ -268,6 +269,7 @@ public class JavacTaskPool {
if (ht.get(Log.logKey) instanceof ReusableLog) {
//log already inited - not first round
Log.instance(this).clear();
LintMapper.instance(this).clear();
Enter.instance(this).newRound();
((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear();
Types.instance(this).newRound();

View File

@ -360,9 +360,14 @@ public class JavacTrees extends DocTrees {
Log.DeferredDiagnosticHandler deferredDiagnosticHandler = log.new DeferredDiagnosticHandler();
try {
Env<AttrContext> env = getAttrContext(path.getTreePath());
Type t = attr.attribType(dcReference.qualifierExpression, env);
if (t != null && !t.isErroneous()) {
return t;
JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
try {
Type t = attr.attribType(dcReference.qualifierExpression, env);
if (t != null && !t.isErroneous()) {
return t;
}
} finally {
log.useSource(prevSource);
}
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
return null;
@ -388,6 +393,7 @@ public class JavacTrees extends DocTrees {
return null;
}
Log.DeferredDiagnosticHandler deferredDiagnosticHandler = log.new DeferredDiagnosticHandler();
JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
try {
final TypeSymbol tsym;
final Name memberName;
@ -509,6 +515,7 @@ public class JavacTrees extends DocTrees {
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
return null;
} finally {
log.useSource(prevSource);
log.popDiagnosticHandler(deferredDiagnosticHandler);
}
}

View File

@ -1,176 +0,0 @@
/*
* Copyright (c) 2011, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.code;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Optional;
import java.util.function.Consumer;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.Tag;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
/**
* Holds pending {@link Lint} warnings until the {@lint Lint} instance associated with the containing
* module, package, class, method, or variable declaration is known so that {@link @SupressWarnings}
* suppressions may be applied.
*
* <p>
* Warnings are regsistered at any time prior to attribution via {@link #report}. The warning will be
* associated with the declaration placed in context by the most recent invocation of {@link #push push()}
* not yet {@link #pop}'d. Warnings are actually emitted later, during attribution, via {@link #flush}.
*
* <p>
* There is also an "immediate" mode, where warnings are emitted synchronously; see {@link #pushImmediate}.
*
* <p>
* Deferred warnings are grouped by the innermost containing module, package, class, method, or variable
* declaration (represented by {@link JCTree} nodes), so that the corresponding {@link Lint} configuration
* can be applied when the warning is eventually generated.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class DeferredLintHandler {
protected static final Context.Key<DeferredLintHandler> deferredLintHandlerKey = new Context.Key<>();
public static DeferredLintHandler instance(Context context) {
DeferredLintHandler instance = context.get(deferredLintHandlerKey);
if (instance == null)
instance = new DeferredLintHandler(context);
return instance;
}
/**
* Registered {@link LintLogger}s grouped by the innermost containing module, package, class,
* method, or variable declaration.
*/
private final HashMap<JCTree, ArrayList<LintLogger>> deferralMap = new HashMap<>();
/**
* The current "reporter" stack, reflecting calls to {@link #push} and {@link #pop}.
*
* <p>
* The top of the stack determines how calls to {@link #report} are handled.
*/
private final ArrayDeque<Consumer<LintLogger>> reporterStack = new ArrayDeque<>();
@SuppressWarnings("this-escape")
protected DeferredLintHandler(Context context) {
context.put(deferredLintHandlerKey, this);
Lint rootLint = Lint.instance(context);
pushImmediate(rootLint); // default to "immediate" mode
}
// LintLogger
/**An interface for deferred lint reporting - loggers passed to
* {@link #report(LintLogger) } will be called when
* {@link #flush(DiagnosticPosition) } is invoked.
*/
public interface LintLogger {
/**
* Generate a warning if appropriate.
*
* @param lint the applicable lint configuration
*/
void report(Lint lint);
}
// Reporter Stack
/**
* Defer {@link #report}ed warnings until the given declaration is flushed.
*
* @param decl module, package, class, method, or variable declaration
* @see #pop
*/
public void push(JCTree decl) {
Assert.check(decl.getTag() == Tag.MODULEDEF
|| decl.getTag() == Tag.PACKAGEDEF
|| decl.getTag() == Tag.CLASSDEF
|| decl.getTag() == Tag.METHODDEF
|| decl.getTag() == Tag.VARDEF);
reporterStack.push(logger -> deferralMap
.computeIfAbsent(decl, s -> new ArrayList<>())
.add(logger));
}
/**
* Enter "immediate" mode so that {@link #report}ed warnings are emitted synchonously.
*
* @param lint lint configuration to use for reported warnings
*/
public void pushImmediate(Lint lint) {
reporterStack.push(logger -> logger.report(lint));
}
/**
* Revert to the previous configuration in effect prior to the most recent invocation
* of {@link #push} or {@link #pushImmediate}.
*
* @see #pop
*/
public void pop() {
Assert.check(reporterStack.size() > 1); // the bottom stack entry should never be popped
reporterStack.pop();
}
/**
* Report a warning.
*
* <p>
* In immediate mode, the warning is emitted synchronously. Otherwise, the warning is emitted later
* when the current declaration is flushed.
*/
public void report(LintLogger logger) {
Assert.check(!reporterStack.isEmpty());
reporterStack.peek().accept(logger);
}
// Warning Flush
/**
* Emit deferred warnings encompassed by the given declaration.
*
* @param decl module, package, class, method, or variable declaration
* @param lint lint configuration corresponding to {@code decl}
*/
public void flush(JCTree decl, Lint lint) {
Optional.of(decl)
.map(deferralMap::remove)
.stream()
.flatMap(ArrayList::stream)
.forEach(logger -> logger.report(lint));
}
}

View File

@ -374,11 +374,8 @@ public class Lint {
/**
* Warn about issues relating to use of text blocks
*
* <p>
* This category is not supported by {@code @SuppressWarnings} (yet - see JDK-8224228).
*/
TEXT_BLOCKS("text-blocks", false),
TEXT_BLOCKS("text-blocks"),
/**
* Warn about possible 'this' escapes before subclass instance is fully initialized.
@ -476,27 +473,6 @@ public class Lint {
return suppressedValues.contains(lc);
}
/**
* Helper method. Log a lint warning if its lint category is enabled.
*
* @param warning key for the localized warning message
*/
public void logIfEnabled(LintWarning warning) {
logIfEnabled(null, warning);
}
/**
* Helper method. Log a lint warning if its lint category is enabled.
*
* @param pos source position at which to report the warning
* @param warning key for the localized warning message
*/
public void logIfEnabled(DiagnosticPosition pos, LintWarning warning) {
if (isEnabled(warning.getLintCategory())) {
log.warning(pos, warning);
}
}
/**
* Obtain the set of recognized lint warning categories suppressed at the given symbol's declaration.
*

View File

@ -0,0 +1,328 @@
/*
* Copyright (c) 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.code;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
* Maps source code positions to the applicable {@link Lint} instance.
*
* <p>
* Because {@code @SuppressWarnings} is a Java symbol, in general this mapping can't be
* calculated until after attribution. As each top-level declaration (class, package, or module)
* is attributed, this singleton is notified and the {@link Lint}s that apply to every source
* position within that top-level declaration are calculated.
*
* <p>
* The method {@link #lintAt} returns the {@link Lint} instance applicable to source position;
* if it can't be determined yet, an empty {@link Optional} is returned.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class LintMapper {
// The key for the context singleton
private static final Context.Key<LintMapper> CONTEXT_KEY = new Context.Key<>();
// Per-source file information. Note: during the parsing of a file, an entry exists but the FileInfo value is null
private final Map<JavaFileObject, FileInfo> fileInfoMap = new HashMap<>();
// Compiler context
private final Context context;
// These are initialized lazily; see initializeIfNeeded()
private Lint rootLint;
/**
* Obtain the {@link LintMapper} context singleton.
*/
public static LintMapper instance(Context context) {
LintMapper instance = context.get(CONTEXT_KEY);
if (instance == null)
instance = new LintMapper(context);
return instance;
}
/**
* Constructor.
*/
@SuppressWarnings("this-escape")
protected LintMapper(Context context) {
context.put(CONTEXT_KEY, this);
this.context = context;
}
// Lazy initialization to avoid dependency loops
private void initializeIfNeeded() {
if (rootLint == null)
rootLint = Lint.instance(context);
}
// Lint Operations
/**
* Determine if the given file is known to this instance.
*
* @param sourceFile source file
* @return true if file is recognized
*/
public boolean isKnown(JavaFileObject sourceFile) {
return fileInfoMap.containsKey(sourceFile);
}
/**
* Obtain the {@link Lint} configuration that applies at the given position, if known.
*
* @param sourceFile source file
* @param pos source position
* @return the applicable {@link Lint}, if known, otherwise empty
*/
public Optional<Lint> lintAt(JavaFileObject sourceFile, DiagnosticPosition pos) {
initializeIfNeeded();
return Optional.of(sourceFile)
.map(fileInfoMap::get)
.flatMap(fileInfo -> fileInfo.lintAt(pos));
}
/**
* Calculate {@lint Lint} configurations for all positions within the given top-level declaration.
*
* @param sourceFile source file
* @param tree top-level declaration (class, package, or module)
*/
public void calculateLints(JavaFileObject sourceFile, JCTree tree, EndPosTable endPositions) {
Assert.check(rootLint != null);
fileInfoMap.get(sourceFile).afterAttr(tree, endPositions);
}
/**
* Reset this instance.
*/
public void clear() {
fileInfoMap.clear();
}
// Parsing Notifications
/**
* Invoked when file parsing starts to create an entry for the new file (but with a null value).
*/
public void startParsingFile(JavaFileObject sourceFile) {
initializeIfNeeded();
fileInfoMap.put(sourceFile, null);
}
/**
* Invoked when file parsing completes to put in place a corresponding {@link FileInfo}.
*/
public void finishParsingFile(JCCompilationUnit tree) {
Assert.check(rootLint != null);
fileInfoMap.put(tree.sourcefile, new FileInfo(rootLint, tree));
}
// FileInfo
/**
* Holds {@link Lint} information for a fully parsed source file.
*
* <p>
* Initially (immediately after parsing), "unmappedDecls" contains a {@link Span} corresponding to each
* top-level declaration in the source file. As each top-level declaration is attributed, the corresponding
* {@link Span} is removed and the corresponding {@link LintRange} subtree is populated under "rootRange".
*/
private static class FileInfo {
final LintRange rootRange; // the root LintRange (covering the entire source file)
final List<Span> unmappedDecls = new ArrayList<>(); // unmapped top-level declarations awaiting attribution
// After parsing: Add top-level declarations to our "unmappedDecls" list
FileInfo(Lint rootLint, JCCompilationUnit tree) {
rootRange = new LintRange(rootLint);
tree.defs.stream()
.filter(this::isTopLevelDecl)
.map(decl -> new Span(decl, tree.endPositions))
.forEach(unmappedDecls::add);
}
// After attribution: Discard the span from "unmappedDecls" and populate the declaration's subtree under "rootRange"
void afterAttr(JCTree tree, EndPosTable endPositions) {
for (Iterator<Span> i = unmappedDecls.iterator(); i.hasNext(); ) {
if (i.next().contains(tree.pos())) {
rootRange.populateSubtree(tree, endPositions);
i.remove();
return;
}
}
throw new AssertionError("top-level declaration not found");
}
// Find the most specific Lint configuration applying to the given position, unless the position has not been mapped yet
Optional<Lint> lintAt(DiagnosticPosition pos) {
boolean mapped = unmappedDecls.stream().noneMatch(span -> span.contains(pos));
return mapped ? Optional.of(rootRange.bestMatch(pos).lint) : Optional.empty();
}
boolean isTopLevelDecl(JCTree tree) {
return tree.getTag() == Tag.MODULEDEF
|| tree.getTag() == Tag.PACKAGEDEF
|| tree.getTag() == Tag.CLASSDEF;
}
}
// Span
/**
* A lexical range.
*/
private record Span(int startPos, int endPos) {
static final Span MAXIMAL = new Span(Integer.MIN_VALUE, Integer.MAX_VALUE);
Span(JCTree tree, EndPosTable endPositions) {
this(TreeInfo.getStartPos(tree), TreeInfo.getEndPos(tree, endPositions));
}
boolean contains(DiagnosticPosition pos) {
int offset = pos.getLintPosition();
return offset == startPos || (offset > startPos && offset < endPos);
}
boolean contains(Span that) {
return this.startPos <= that.startPos && this.endPos >= that.endPos;
}
}
// LintRange
/**
* A tree of nested lexical ranges and the {@link Lint} configurations that apply therein.
*/
private record LintRange(
Span span, // declaration's lexical range
Lint lint, // the Lint configuration that applies at this declaration
List<LintRange> children // the nested declarations one level below this node
) {
// Create a node representing the entire file, using the root lint configuration
LintRange(Lint rootLint) {
this(Span.MAXIMAL, rootLint, new ArrayList<>());
}
// Create a node representing the given declaration and its corresponding Lint configuration
LintRange(JCTree tree, EndPosTable endPositions, Lint lint) {
this(new Span(tree, endPositions), lint, new ArrayList<>());
}
// Find the most specific node in this tree (including me) that contains the given position, if any
LintRange bestMatch(DiagnosticPosition pos) {
return children.stream()
.map(child -> child.bestMatch(pos))
.filter(Objects::nonNull)
.reduce((a, b) -> a.span.contains(b.span) ? b : a)
.orElseGet(() -> span.contains(pos) ? this : null);
}
// Populate a sparse subtree corresponding to the given nested declaration.
// Only when the Lint configuration differs from the parent is a node added.
void populateSubtree(JCTree tree, EndPosTable endPositions) {
new TreeScanner() {
private LintRange currentNode = LintRange.this;
@Override
public void visitModuleDef(JCModuleDecl tree) {
scanDecl(tree, tree.sym, super::visitModuleDef);
}
@Override
public void visitPackageDef(JCPackageDecl tree) {
scanDecl(tree, tree.packge, super::visitPackageDef);
}
@Override
public void visitClassDef(JCClassDecl tree) {
scanDecl(tree, tree.sym, super::visitClassDef);
}
@Override
public void visitMethodDef(JCMethodDecl tree) {
scanDecl(tree, tree.sym, super::visitMethodDef);
}
@Override
public void visitVarDef(JCVariableDecl tree) {
scanDecl(tree, tree.sym, super::visitVarDef);
}
private <T extends JCTree> void scanDecl(T tree, Symbol symbol, Consumer<? super T> recursor) {
// The "symbol" can be null if there were earlier errors; skip this declaration if so
if (symbol == null) {
recursor.accept(tree);
return;
}
// Update the Lint using the declaration; if there's no change, then we don't need a new node here
Lint newLint = currentNode.lint.augment(symbol);
if (newLint == currentNode.lint) { // note: lint.augment() returns the same instance if there's no change
recursor.accept(tree);
return;
}
// Add a new node here and proceed
final LintRange previousNode = currentNode;
currentNode = new LintRange(tree, endPositions, newLint);
previousNode.children.add(currentNode);
try {
recursor.accept(tree);
} finally {
currentNode = previousNode;
}
}
}.scan(tree);
}
}
}

View File

@ -67,9 +67,6 @@ public class Preview {
/** flag: are preview features enabled */
private final boolean enabled;
/** flag: is the "preview" lint category enabled? */
private final boolean verbose;
/** test flag: should all features be considered as preview features? */
private final boolean forcePreview;
@ -100,7 +97,6 @@ public class Preview {
enabled = options.isSet(PREVIEW);
log = Log.instance(context);
source = Source.instance(context);
verbose = Lint.instance(context).isEnabled(LintCategory.PREVIEW);
forcePreview = options.isSet("forcePreview");
majorVersionToSource = initMajorVersionToSourceMap();
}
@ -184,9 +180,7 @@ public class Preview {
*/
public void warnPreview(JavaFileObject classfile, int majorVersion) {
Assert.check(isEnabled());
if (verbose) {
log.warning(LintWarnings.PreviewFeatureUseClassfile(classfile, majorVersionToSource.get(majorVersion).name));
}
log.warning(LintWarnings.PreviewFeatureUseClassfile(classfile, majorVersionToSource.get(majorVersion).name));
}
/**

View File

@ -89,9 +89,7 @@ public class Annotate {
private final Attr attr;
private final Check chk;
private final ConstFold cfolder;
private final DeferredLintHandler deferredLintHandler;
private final Enter enter;
private final Lint lint;
private final Log log;
private final Names names;
private final Resolve resolve;
@ -110,10 +108,8 @@ public class Annotate {
attr = Attr.instance(context);
chk = Check.instance(context);
cfolder = ConstFold.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
enter = Enter.instance(context);
log = Log.instance(context);
lint = Lint.instance(context);
make = TreeMaker.instance(context);
names = Names.instance(context);
resolve = Resolve.instance(context);
@ -235,10 +231,8 @@ public class Annotate {
* @param annotations the list of JCAnnotations to attribute and enter
* @param localEnv the enclosing env
* @param s the Symbol on which to enter the annotations
* @param deferDecl enclosing declaration for DeferredLintHandler, or null for no deferral
*/
public void annotateLater(List<JCAnnotation> annotations, Env<AttrContext> localEnv,
Symbol s, JCTree deferDecl)
public void annotateLater(List<JCAnnotation> annotations, Env<AttrContext> localEnv, Symbol s)
{
if (annotations.isEmpty()) {
return;
@ -256,8 +250,6 @@ public class Annotate {
// been handled, meaning that the set of annotations pending completion is now empty.
Assert.check(s.kind == PCK || s.annotationsPendingCompletion());
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
Assert.check(deferDecl != null);
deferredLintHandler.push(deferDecl);
try {
if (s.hasAnnotations() && annotations.nonEmpty())
log.error(annotations.head.pos, Errors.AlreadyAnnotated(Kinds.kindName(s), s));
@ -268,7 +260,6 @@ public class Annotate {
// never called for a type parameter
annotateNow(s, annotations, localEnv, false, false);
} finally {
deferredLintHandler.pop();
log.useSource(prev);
}
});
@ -285,16 +276,13 @@ public class Annotate {
/** Queue processing of an attribute default value. */
public void annotateDefaultValueLater(JCExpression defaultValue, Env<AttrContext> localEnv,
MethodSymbol m, JCTree deferDecl)
public void annotateDefaultValueLater(JCExpression defaultValue, Env<AttrContext> localEnv, MethodSymbol m)
{
normal(() -> {
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
deferredLintHandler.push(deferDecl);
try {
enterDefaultValue(defaultValue, localEnv, m);
} finally {
deferredLintHandler.pop();
log.useSource(prev);
}
});
@ -682,7 +670,7 @@ public class Annotate {
// Scan the annotation element value and then attribute nested annotations if present
if (tree.type != null && tree.type.tsym != null) {
queueScanTreeAndTypeAnnotate(tree, env, tree.type.tsym, null);
queueScanTreeAndTypeAnnotate(tree, env, tree.type.tsym);
}
result = cfolder.coerce(result, expectedElementType);
@ -1034,20 +1022,14 @@ public class Annotate {
/**
* Attribute the list of annotations and enter them onto s.
*/
public void enterTypeAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env,
Symbol s, JCTree deferDecl, boolean isTypeParam)
public void enterTypeAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env, Symbol s, boolean isTypeParam)
{
Assert.checkNonNull(s, "Symbol argument to actualEnterTypeAnnotations is nul/");
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
if (deferDecl != null) {
deferredLintHandler.push(deferDecl);
}
try {
annotateNow(s, annotations, env, true, isTypeParam);
} finally {
if (deferDecl != null)
deferredLintHandler.pop();
log.useSource(prev);
}
}
@ -1055,10 +1037,10 @@ public class Annotate {
/**
* Enqueue tree for scanning of type annotations, attaching to the Symbol sym.
*/
public void queueScanTreeAndTypeAnnotate(JCTree tree, Env<AttrContext> env, Symbol sym, JCTree deferDecl)
public void queueScanTreeAndTypeAnnotate(JCTree tree, Env<AttrContext> env, Symbol sym)
{
Assert.checkNonNull(sym);
normal(() -> tree.accept(new TypeAnnotate(env, sym, deferDecl)));
normal(() -> tree.accept(new TypeAnnotate(env, sym)));
}
/**
@ -1093,32 +1075,30 @@ public class Annotate {
private class TypeAnnotate extends TreeScanner {
private final Env<AttrContext> env;
private final Symbol sym;
private JCTree deferDecl;
public TypeAnnotate(Env<AttrContext> env, Symbol sym, JCTree deferDecl) {
public TypeAnnotate(Env<AttrContext> env, Symbol sym) {
this.env = env;
this.sym = sym;
this.deferDecl = deferDecl;
}
@Override
public void visitAnnotatedType(JCAnnotatedType tree) {
enterTypeAnnotations(tree.annotations, env, sym, deferDecl, false);
enterTypeAnnotations(tree.annotations, env, sym, false);
scan(tree.underlyingType);
}
@Override
public void visitTypeParameter(JCTypeParameter tree) {
enterTypeAnnotations(tree.annotations, env, sym, deferDecl, true);
enterTypeAnnotations(tree.annotations, env, sym, true);
scan(tree.bounds);
}
@Override
public void visitNewArray(JCNewArray tree) {
enterTypeAnnotations(tree.annotations, env, sym, deferDecl, false);
enterTypeAnnotations(tree.annotations, env, sym, false);
for (List<JCAnnotation> dimAnnos : tree.dimAnnotations)
enterTypeAnnotations(dimAnnos, env, sym, deferDecl, false);
enterTypeAnnotations(dimAnnos, env, sym, false);
scan(tree.elemtype);
scan(tree.elems);
}
@ -1137,19 +1117,13 @@ public class Annotate {
@Override
public void visitVarDef(JCVariableDecl tree) {
JCTree prevDecl = deferDecl;
deferDecl = tree;
try {
if (sym != null && sym.kind == VAR) {
// Don't visit a parameter once when the sym is the method
// and once when the sym is the parameter.
scan(tree.mods);
scan(tree.vartype);
}
scan(tree.init);
} finally {
deferDecl = prevDecl;
if (sym != null && sym.kind == VAR) {
// Don't visit a parameter once when the sym is the method
// and once when the sym is the parameter.
scan(tree.mods);
scan(tree.vartype);
}
scan(tree.init);
}
@Override

View File

@ -41,6 +41,7 @@ import com.sun.source.tree.TreeVisitor;
import com.sun.source.util.SimpleTreeVisitor;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Symbol.*;
@ -98,6 +99,7 @@ public class Attr extends JCTree.Visitor {
final Names names;
final Log log;
final LintMapper lintMapper;
final Symtab syms;
final Resolve rs;
final Operators operators;
@ -116,7 +118,6 @@ public class Attr extends JCTree.Visitor {
final Preview preview;
final JCDiagnostic.Factory diags;
final TypeAnnotations typeAnnotations;
final DeferredLintHandler deferredLintHandler;
final TypeEnvs typeEnvs;
final Dependencies dependencies;
final Annotate annotate;
@ -137,6 +138,7 @@ public class Attr extends JCTree.Visitor {
names = Names.instance(context);
log = Log.instance(context);
lintMapper = LintMapper.instance(context);
syms = Symtab.instance(context);
rs = Resolve.instance(context);
operators = Operators.instance(context);
@ -156,7 +158,6 @@ public class Attr extends JCTree.Visitor {
diags = JCDiagnostic.Factory.instance(context);
annotate = Annotate.instance(context);
typeAnnotations = TypeAnnotations.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
typeEnvs = TypeEnvs.instance(context);
dependencies = Dependencies.instance(context);
argumentAttr = ArgumentAttr.instance(context);
@ -853,7 +854,6 @@ public class Attr extends JCTree.Visitor {
Env<AttrContext> enclosingEnv,
JCVariableDecl variable,
Type type) {
deferredLintHandler.push(variable);
final JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
try {
doQueueScanTreeAndTypeAnnotateForVarInit(variable, enclosingEnv);
@ -869,7 +869,6 @@ public class Attr extends JCTree.Visitor {
}
} finally {
log.useSource(prevSource);
deferredLintHandler.pop();
}
}
@ -998,7 +997,6 @@ public class Attr extends JCTree.Visitor {
Assert.check(!env.info.ctorPrologue);
MethodSymbol prevMethod = chk.setMethod(m);
try {
deferredLintHandler.flush(tree, lint);
chk.checkDeprecatedAnnotation(tree.pos(), m);
@ -1233,7 +1231,7 @@ public class Attr extends JCTree.Visitor {
}
// Attribute all type annotations in the body
annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m, null);
annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m);
annotate.flush();
// Start of constructor prologue (if not in java.lang.Object constructor)
@ -1297,7 +1295,6 @@ public class Attr extends JCTree.Visitor {
try {
v.getConstValue(); // ensure compile-time constant initializer is evaluated
deferredLintHandler.flush(tree, lint);
chk.checkDeprecatedAnnotation(tree.pos(), v);
if (tree.init != null) {
@ -1342,7 +1339,7 @@ public class Attr extends JCTree.Visitor {
env.info.scope.owner.kind != MTH && env.info.scope.owner.kind != VAR) {
tree.mods.flags |= Flags.FIELD_INIT_TYPE_ANNOTATIONS_QUEUED;
// Field initializer expression need to be entered.
annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym, tree);
annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym);
annotate.flush();
}
}
@ -1439,7 +1436,7 @@ public class Attr extends JCTree.Visitor {
if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
// Attribute all type annotations in the block
annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner, null);
annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner);
annotate.flush();
attribStats(tree.stats, localEnv);
@ -1952,7 +1949,7 @@ public class Attr extends JCTree.Visitor {
public void visitSynchronized(JCSynchronized tree) {
chk.checkRefType(tree.pos(), attribExpr(tree.lock, env));
if (tree.lock.type != null && tree.lock.type.isValueBased()) {
env.info.lint.logIfEnabled(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
log.warning(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
}
attribStat(tree.body, env);
result = null;
@ -2054,7 +2051,7 @@ public class Attr extends JCTree.Visitor {
if (close.kind == MTH &&
close.overrides(syms.autoCloseableClose, resource.tsym, types, true) &&
chk.isHandled(syms.interruptedExceptionType, types.memberType(resource, close).getThrownTypes())) {
env.info.lint.logIfEnabled(pos, LintWarnings.TryResourceThrowsInterruptedExc(resource));
log.warning(pos, LintWarnings.TryResourceThrowsInterruptedExc(resource));
}
}
}
@ -4226,9 +4223,9 @@ public class Attr extends JCTree.Visitor {
setSyntheticVariableType(tree.var, type == Type.noType ? syms.errType
: type);
}
annotate.annotateLater(tree.var.mods.annotations, env, v, tree.var);
annotate.annotateLater(tree.var.mods.annotations, env, v);
if (!tree.var.isImplicitlyTyped()) {
annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v, tree.var);
annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v);
}
annotate.flush();
result = tree.type;
@ -4466,7 +4463,7 @@ public class Attr extends JCTree.Visitor {
sym.kind == MTH &&
sym.name.equals(names.close) &&
sym.overrides(syms.autoCloseableClose, sitesym.type.tsym, types, true)) {
env.info.lint.logIfEnabled(tree, LintWarnings.TryExplicitCloseCall);
log.warning(tree, LintWarnings.TryExplicitCloseCall);
}
// Disallow selecting a type from an expression
@ -4493,9 +4490,9 @@ public class Attr extends JCTree.Visitor {
// If the qualified item is not a type and the selected item is static, report
// a warning. Make allowance for the class of an array type e.g. Object[].class)
if (!sym.owner.isAnonymous()) {
chk.lint.logIfEnabled(tree, LintWarnings.StaticNotQualifiedByType(sym.kind.kindName(), sym.owner));
log.warning(tree, LintWarnings.StaticNotQualifiedByType(sym.kind.kindName(), sym.owner));
} else {
chk.lint.logIfEnabled(tree, LintWarnings.StaticNotQualifiedByType2(sym.kind.kindName()));
log.warning(tree, LintWarnings.StaticNotQualifiedByType2(sym.kind.kindName()));
}
}
@ -5297,6 +5294,9 @@ public class Attr extends JCTree.Visitor {
}
annotate.flush();
// Now that this tree is attributed, we can calculate the Lint configuration everywhere within it
lintMapper.calculateLints(env.toplevel.sourcefile, env.tree, env.toplevel.endPositions);
}
public void attribPackage(DiagnosticPosition pos, PackageSymbol p) {
@ -5339,7 +5339,6 @@ public class Attr extends JCTree.Visitor {
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
try {
deferredLintHandler.flush(env.tree, lint);
attrib.accept(env);
} finally {
log.useSource(prev);
@ -5523,7 +5522,6 @@ public class Attr extends JCTree.Visitor {
}
}
deferredLintHandler.flush(env.tree, env.info.lint);
env.info.returnResult = null;
// java.lang.Enum may not be subclassed by a non-enum
if (st.tsym == syms.enumSym &&
@ -5569,11 +5567,9 @@ public class Attr extends JCTree.Visitor {
ModuleSymbol msym = tree.sym;
Lint lint = env.outer.info.lint = env.outer.info.lint.augment(msym);
Lint prevLint = chk.setLint(lint);
chk.checkModuleName(tree);
chk.checkDeprecatedAnnotation(tree, msym);
try {
deferredLintHandler.flush(tree, lint);
chk.checkModuleName(tree);
chk.checkDeprecatedAnnotation(tree, msym);
} finally {
chk.setLint(prevLint);
}

View File

@ -121,7 +121,7 @@ public class Check {
// The set of lint options currently in effect. It is initialized
// from the context, and then is set/reset as needed by Attr as it
// visits all the various parts of the trees during attribution.
Lint lint;
private Lint lint;
// The method being analyzed in Attr - it is set/reset as needed by
// Attr as it visits new method declarations.
@ -164,8 +164,6 @@ public class Check {
profile = Profile.instance(context);
preview = Preview.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
allowModules = Feature.MODULES.allowedInSource(source);
allowRecords = Feature.RECORDS.allowedInSource(source);
allowSealed = Feature.SEALED_CLASSES.allowedInSource(source);
@ -180,10 +178,6 @@ public class Check {
*/
private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
/** A handler for deferred lint warnings.
*/
private DeferredLintHandler deferredLintHandler;
/** Are modules allowed
*/
private final boolean allowModules;
@ -229,24 +223,15 @@ 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) {
warningKey = LintWarnings.HasBeenDeprecatedForRemovalModule(sym);
} else {
warningKey = LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location());
}
}
} else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
if (sym.kind == MDL) {
warningKey = LintWarnings.HasBeenDeprecatedModule(sym);
} else {
warningKey = LintWarnings.HasBeenDeprecated(sym, sym.location());
}
}
if (warningKey != null)
log.warning(pos, warningKey);
Assert.check(!importSuppression);
LintWarning warningKey = sym.isDeprecatedForRemoval() ?
(sym.kind == MDL ?
LintWarnings.HasBeenDeprecatedForRemovalModule(sym) :
LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location())) :
(sym.kind == MDL ?
LintWarnings.HasBeenDeprecatedModule(sym) :
LintWarnings.HasBeenDeprecated(sym, sym.location()));
log.warning(pos, warningKey);
}
/** Log a preview warning.
@ -254,25 +239,16 @@ public class Check {
* @param msg A Warning describing the problem.
*/
public void warnPreviewAPI(DiagnosticPosition pos, LintWarning warnKey) {
if (!importSuppression && !lint.isSuppressed(LintCategory.PREVIEW))
if (!importSuppression)
log.warning(pos, warnKey);
}
/** Log a preview warning.
* @param pos Position to be used for error reporting.
* @param msg A Warning describing the problem.
*/
public void warnRestrictedAPI(DiagnosticPosition pos, Symbol sym) {
lint.logIfEnabled(pos, LintWarnings.RestrictedMethod(sym.enclClass(), sym));
}
/** Warn about unchecked operation.
* @param pos Position to be used for error reporting.
* @param msg A string describing the problem.
*/
public void warnUnchecked(DiagnosticPosition pos, LintWarning warnKey) {
if (!lint.isSuppressed(LintCategory.UNCHECKED))
log.warning(pos, warnKey);
log.warning(pos, warnKey);
}
/** Report a failure to complete a class.
@ -608,9 +584,7 @@ public class Check {
&& types.isSameType(tree.expr.type, tree.clazz.type)
&& !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz))
&& !is292targetTypeCast(tree)) {
deferredLintHandler.report(_l -> {
lint.logIfEnabled(tree.pos(), LintWarnings.RedundantCast(tree.clazz.type));
});
log.warning(tree.pos(), LintWarnings.RedundantCast(tree.clazz.type));
}
}
//where
@ -914,7 +888,7 @@ public class Check {
}
} else if (hasTrustMeAnno && varargElemType != null &&
types.isReifiable(varargElemType)) {
lint.logIfEnabled(tree, LintWarnings.VarargsRedundantTrustmeAnno(
log.warning(tree.pos(), LintWarnings.VarargsRedundantTrustmeAnno(
syms.trustMeType.tsym,
diags.fragment(Fragments.VarargsTrustmeOnReifiableVarargs(varargElemType))));
}
@ -1173,7 +1147,7 @@ public class Check {
mask = MethodFlags;
}
if ((flags & STRICTFP) != 0) {
warnOnExplicitStrictfp(tree);
log.warning(tree.pos(), LintWarnings.Strictfp);
}
// Imply STRICTFP if owner has STRICTFP set.
if (((flags|implicit) & Flags.ABSTRACT) == 0 ||
@ -1217,7 +1191,7 @@ public class Check {
implicit |= FINAL;
}
if ((flags & STRICTFP) != 0) {
warnOnExplicitStrictfp(tree);
log.warning(tree.pos(), LintWarnings.Strictfp);
}
// Imply STRICTFP if owner has STRICTFP set.
implicit |= sym.owner.flags_field & STRICTFP;
@ -1281,16 +1255,6 @@ public class Check {
return flags & (mask | ~ExtendedStandardFlags) | implicit;
}
private void warnOnExplicitStrictfp(JCTree tree) {
deferredLintHandler.push(tree);
try {
deferredLintHandler.report(_ -> lint.logIfEnabled(tree.pos(), LintWarnings.Strictfp));
} finally {
deferredLintHandler.pop();
}
}
/** Determine if this enum should be implicitly final.
*
* If the enum has no specialized enum constants, it is final.
@ -1503,7 +1467,7 @@ public class Check {
!TreeInfo.isDiamond(tree) &&
!withinAnonConstr(env) &&
tree.type.isRaw()) {
lint.logIfEnabled(tree.pos(), LintWarnings.RawClassUse(tree.type, tree.type.tsym.type));
log.warning(tree.pos(), LintWarnings.RawClassUse(tree.type, tree.type.tsym.type));
}
}
//where
@ -1827,7 +1791,7 @@ public class Check {
// Optional warning if varargs don't agree
if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)) {
lint.logIfEnabled(TreeInfo.diagnosticPositionFor(m, tree),
log.warning(TreeInfo.diagnosticPositionFor(m, tree),
((m.flags() & Flags.VARARGS) != 0)
? LintWarnings.OverrideVarargsMissing(varargsOverrides(m, other))
: LintWarnings.OverrideVarargsExtra(varargsOverrides(m, other)));
@ -1841,12 +1805,7 @@ public class Check {
// Warn if a deprecated method overridden by a non-deprecated one.
if (!isDeprecatedOverrideIgnorable(other, origin)) {
Lint prevLint = setLint(lint.augment(m));
try {
checkDeprecated(() -> TreeInfo.diagnosticPositionFor(m, tree), m, other);
} finally {
setLint(prevLint);
}
checkDeprecated(() -> TreeInfo.diagnosticPositionFor(m, tree), m, other);
}
}
// where
@ -2915,42 +2874,33 @@ public class Check {
// Apply special flag "-XDwarnOnAccessToMembers" which turns on just this particular warning for all types of access
void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) {
final Lint prevLint = setLint(warnOnAnyAccessToMembers ? lint.enable(LintCategory.SERIAL) : lint);
try {
if (warnOnAnyAccessToMembers || isLambda)
checkAccessFromSerializableElementInner(tree, isLambda);
} finally {
setLint(prevLint);
}
if (warnOnAnyAccessToMembers || isLambda)
checkAccessFromSerializableElementInner(tree, isLambda);
}
private void checkAccessFromSerializableElementInner(final JCTree tree, boolean isLambda) {
if (lint.isEnabled(LintCategory.SERIAL)) {
Symbol sym = TreeInfo.symbol(tree);
if (!sym.kind.matches(KindSelector.VAL_MTH)) {
Symbol sym = TreeInfo.symbol(tree);
if (!sym.kind.matches(KindSelector.VAL_MTH)) {
return;
}
if (sym.kind == VAR) {
if ((sym.flags() & PARAMETER) != 0 ||
sym.isDirectlyOrIndirectlyLocal() ||
sym.name == names._this ||
sym.name == names._super) {
return;
}
}
if (sym.kind == VAR) {
if ((sym.flags() & PARAMETER) != 0 ||
sym.isDirectlyOrIndirectlyLocal() ||
sym.name == names._this ||
sym.name == names._super) {
return;
}
}
if (!types.isSubtype(sym.owner.type, syms.serializableType) &&
isEffectivelyNonPublic(sym)) {
if (isLambda) {
if (belongsToRestrictedPackage(sym)) {
log.warning(tree.pos(),
LintWarnings.AccessToMemberFromSerializableLambda(sym));
}
} else {
log.warning(tree.pos(),
LintWarnings.AccessToMemberFromSerializableElement(sym));
if (!types.isSubtype(sym.owner.type, syms.serializableType) && isEffectivelyNonPublic(sym)) {
DiagnosticFlag flag = warnOnAnyAccessToMembers ? DiagnosticFlag.DEFAULT_ENABLED : null;
if (isLambda) {
if (belongsToRestrictedPackage(sym)) {
log.warning(flag, tree.pos(), LintWarnings.AccessToMemberFromSerializableLambda(sym));
}
} else {
log.warning(flag, tree.pos(), LintWarnings.AccessToMemberFromSerializableElement(sym));
}
}
}
@ -3737,8 +3687,7 @@ public class Check {
// Note: @Deprecated has no effect on local variables, parameters and package decls.
if (lint.isEnabled(LintCategory.DEPRECATION) && !s.isDeprecatableViaAnnotation()) {
if (!syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) != null) {
log.warning(pos,
LintWarnings.DeprecatedAnnotationHasNoEffect(Kinds.kindName(s)));
log.warning(pos, LintWarnings.DeprecatedAnnotationHasNoEffect(Kinds.kindName(s)));
}
}
}
@ -3752,15 +3701,13 @@ public class Check {
&& (s.isDeprecatedForRemoval() || s.isDeprecated() && !other.isDeprecated())
&& (s.outermostClass() != other.outermostClass() || s.outermostClass() == null)
&& s.kind != Kind.PCK) {
deferredLintHandler.report(_l -> warnDeprecated(pos.get(), s));
warnDeprecated(pos.get(), s);
}
}
void checkSunAPI(final DiagnosticPosition pos, final Symbol s) {
if ((s.flags() & PROPRIETARY) != 0) {
deferredLintHandler.report(_l -> {
log.warning(pos, Warnings.SunProprietary(s));
});
log.warning(pos, Warnings.SunProprietary(s));
}
}
@ -3817,7 +3764,7 @@ public class Check {
void checkRestricted(DiagnosticPosition pos, Symbol s) {
if (s.kind == MTH && (s.flags() & RESTRICTED) != 0) {
deferredLintHandler.report(_l -> warnRestrictedAPI(pos, s));
log.warning(pos, LintWarnings.RestrictedMethod(s.enclClass(), s));
}
}
@ -4089,7 +4036,7 @@ public class Check {
int opc = ((OperatorSymbol)operator).opcode;
if (opc == ByteCodes.idiv || opc == ByteCodes.imod
|| opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
deferredLintHandler.report(_ -> lint.logIfEnabled(pos, LintWarnings.DivZero));
log.warning(pos, LintWarnings.DivZero);
}
}
}
@ -4102,8 +4049,7 @@ public class Check {
*/
void checkLossOfPrecision(final DiagnosticPosition pos, Type found, Type req) {
if (found.isNumeric() && req.isNumeric() && !types.isAssignable(found, req)) {
deferredLintHandler.report(_ ->
lint.logIfEnabled(pos, LintWarnings.PossibleLossOfPrecision(found, req)));
log.warning(pos, LintWarnings.PossibleLossOfPrecision(found, req));
}
}
@ -4112,7 +4058,7 @@ public class Check {
*/
void checkEmptyIf(JCIf tree) {
if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null) {
lint.logIfEnabled(tree.thenpart.pos(), LintWarnings.EmptyIf);
log.warning(tree.thenpart.pos(), LintWarnings.EmptyIf);
}
}
@ -4259,8 +4205,7 @@ public class Check {
rs.isAccessible(env, c) &&
!fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile))
{
lint.logIfEnabled(pos,
LintWarnings.AuxiliaryClassAccessedFromOutsideOfItsSourceFile(c, c.sourcefile));
log.warning(pos, LintWarnings.AuxiliaryClassAccessedFromOutsideOfItsSourceFile(c, c.sourcefile));
}
}
@ -4302,8 +4247,7 @@ public class Check {
// Warning may be suppressed by
// annotations; check again for being
// enabled in the deferred context.
deferredLintHandler.report(_ ->
lint.logIfEnabled(pos, LintWarnings.MissingExplicitCtor(c, pkg, modle)));
log.warning(pos, LintWarnings.MissingExplicitCtor(c, pkg, modle));
} else {
return;
}
@ -4339,7 +4283,7 @@ public class Check {
method.attribute(syms.trustMeType.tsym) != null &&
isTrustMeAllowedOnMethod(method) &&
!types.isReifiable(method.type.getParameterTypes().last())) {
Check.this.lint.logIfEnabled(pos(), LintWarnings.VarargsUnsafeUseVarargsParam(method.params.last()));
log.warning(pos(), LintWarnings.VarargsUnsafeUseVarargsParam(method.params.last()));
}
break;
default:
@ -4637,28 +4581,24 @@ public class Check {
void checkModuleExists(final DiagnosticPosition pos, ModuleSymbol msym) {
if (msym.kind != MDL) {
deferredLintHandler.report(_ ->
lint.logIfEnabled(pos, LintWarnings.ModuleNotFound(msym)));
log.warning(pos, LintWarnings.ModuleNotFound(msym));
}
}
void checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge) {
if (packge.members().isEmpty() &&
((packge.flags() & Flags.HAS_RESOURCE) == 0)) {
deferredLintHandler.report(_ ->
lint.logIfEnabled(pos, LintWarnings.PackageEmptyOrNotFound(packge)));
log.warning(pos, LintWarnings.PackageEmptyOrNotFound(packge));
}
}
void checkModuleRequires(final DiagnosticPosition pos, final RequiresDirective rd) {
if ((rd.module.flags() & Flags.AUTOMATIC_MODULE) != 0) {
deferredLintHandler.report(_ -> {
if (rd.isTransitive() && lint.isEnabled(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC)) {
log.warning(pos, LintWarnings.RequiresTransitiveAutomatic);
} else {
lint.logIfEnabled(pos, LintWarnings.RequiresAutomatic);
}
});
if (rd.isTransitive()) { // see comment in Log.applyLint() for special logic that applies
log.warning(pos, LintWarnings.RequiresTransitiveAutomatic);
} else {
log.warning(pos, LintWarnings.RequiresAutomatic);
}
}
}
@ -5693,14 +5633,14 @@ public class Check {
VarSymbol lastParam = ms.params.head;
for (VarSymbol param: ms.params) {
if ((param.flags_field & REQUIRES_IDENTITY) != 0 && argExps.head.type.isValueBased()) {
lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
log.warning(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
}
lastParam = param;
argExps = argExps.tail;
}
while (argExps != null && !argExps.isEmpty() && lastParam != null) {
if ((lastParam.flags_field & REQUIRES_IDENTITY) != 0 && argExps.head.type.isValueBased()) {
lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
log.warning(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
}
argExps = argExps.tail;
}
@ -5727,7 +5667,7 @@ public class Check {
// we need to avoid recursion due to self referencing type vars or captures, this is why we need a set
requiresIdentityVisitor.visit(t, new HashSet<>());
if (requiresIdentityVisitor.requiresWarning) {
lint.logIfEnabled(pos, LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
log.warning(pos, LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
return true;
}
}
@ -5804,7 +5744,7 @@ public class Check {
.filter(ta -> isRequiresIdentityAnnotation(ta.type.tsym) &&
typeParamTrees.get(ta.position.parameter_index).type != null &&
typeParamTrees.get(ta.position.parameter_index).type.isValueBased())
.forEach(ta -> lint.logIfEnabled(typeParamTrees.get(ta.position.parameter_index).pos(),
.forEach(ta -> log.warning(typeParamTrees.get(ta.position.parameter_index).pos(),
CompilerProperties.LintWarnings.AttemptToUseValueBasedWhereIdentityExpected));
}
}

View File

@ -214,7 +214,6 @@ public class Flow {
private final Resolve rs;
private final JCDiagnostic.Factory diags;
private Env<AttrContext> attrEnv;
private Lint lint;
private final Infer infer;
public static Flow instance(Context context) {
@ -337,7 +336,6 @@ public class Flow {
syms = Symtab.instance(context);
types = Types.instance(context);
chk = Check.instance(context);
lint = Lint.instance(context);
infer = Infer.instance(context);
rs = Resolve.instance(context);
diags = JCDiagnostic.Factory.instance(context);
@ -562,10 +560,8 @@ public class Flow {
if (tree.sym == null) return;
Liveness alivePrev = alive;
ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
Lint lintPrev = lint;
pendingExits = new ListBuffer<>();
lint = lint.augment(tree.sym);
try {
// process all the nested classes
@ -596,30 +592,22 @@ public class Flow {
} finally {
pendingExits = pendingExitsPrev;
alive = alivePrev;
lint = lintPrev;
}
}
public void visitMethodDef(JCMethodDecl tree) {
if (tree.body == null) return;
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
Assert.check(pendingExits.isEmpty());
try {
alive = Liveness.ALIVE;
scanStat(tree.body);
tree.completesNormally = alive != Liveness.DEAD;
alive = Liveness.ALIVE;
scanStat(tree.body);
tree.completesNormally = alive != Liveness.DEAD;
if (alive == Liveness.ALIVE && !tree.sym.type.getReturnType().hasTag(VOID))
log.error(TreeInfo.diagEndPos(tree.body), Errors.MissingRetStmt);
if (alive == Liveness.ALIVE && !tree.sym.type.getReturnType().hasTag(VOID))
log.error(TreeInfo.diagEndPos(tree.body), Errors.MissingRetStmt);
clearPendingExits(true);
} finally {
lint = lintPrev;
}
clearPendingExits(true);
}
private void clearPendingExits(boolean inMethod) {
@ -634,15 +622,7 @@ public class Flow {
}
public void visitVarDef(JCVariableDecl tree) {
if (tree.init != null) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try{
scan(tree.init);
} finally {
lint = lintPrev;
}
}
scan(tree.init);
}
public void visitBlock(JCBlock tree) {
@ -724,8 +704,7 @@ public class Flow {
// Warn about fall-through if lint switch fallthrough enabled.
if (alive == Liveness.ALIVE &&
c.stats.nonEmpty() && l.tail.nonEmpty())
lint.logIfEnabled(l.tail.head.pos(),
LintWarnings.PossibleFallThroughIntoCase);
log.warning(l.tail.head.pos(), LintWarnings.PossibleFallThroughIntoCase);
}
tree.isExhaustive = tree.hasUnconditionalPattern ||
TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases);
@ -1232,7 +1211,7 @@ public class Flow {
scanStat(tree.finalizer);
tree.finallyCanCompleteNormally = alive != Liveness.DEAD;
if (alive == Liveness.DEAD) {
lint.logIfEnabled(TreeInfo.diagEndPos(tree.finalizer),
log.warning(TreeInfo.diagEndPos(tree.finalizer),
LintWarnings.FinallyCannotComplete);
} else {
while (exits.nonEmpty()) {
@ -1453,7 +1432,6 @@ public class Flow {
List<Type> thrownPrev = thrown;
List<Type> caughtPrev = caught;
ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
Lint lintPrev = lint;
boolean anonymousClass = tree.name == names.empty;
pendingExits = new ListBuffer<>();
if (!anonymousClass) {
@ -1461,7 +1439,6 @@ public class Flow {
}
classDef = tree;
thrown = List.nil();
lint = lint.augment(tree.sym);
try {
// process all the nested classes
@ -1510,7 +1487,6 @@ public class Flow {
pendingExits = pendingExitsPrev;
caught = caughtPrev;
classDef = classDefPrev;
lint = lintPrev;
}
}
@ -1519,9 +1495,6 @@ public class Flow {
List<Type> caughtPrev = caught;
List<Type> mthrown = tree.sym.type.getThrownTypes();
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
Assert.check(pendingExits.isEmpty());
@ -1554,20 +1527,11 @@ public class Flow {
}
} finally {
caught = caughtPrev;
lint = lintPrev;
}
}
public void visitVarDef(JCVariableDecl tree) {
if (tree.init != null) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try{
scan(tree.init);
} finally {
lint = lintPrev;
}
}
scan(tree.init);
}
public void visitBlock(JCBlock tree) {
@ -2387,82 +2351,76 @@ public class Flow {
return;
}
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
JCClassDecl classDefPrev = classDef;
int firstadrPrev = firstadr;
int nextadrPrev = nextadr;
ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
pendingExits = new ListBuffer<>();
if (tree.name != names.empty) {
firstadr = nextadr;
}
classDef = tree;
try {
JCClassDecl classDefPrev = classDef;
int firstadrPrev = firstadr;
int nextadrPrev = nextadr;
ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
pendingExits = new ListBuffer<>();
if (tree.name != names.empty) {
firstadr = nextadr;
// define all the static fields
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(VARDEF)) {
JCVariableDecl def = (JCVariableDecl)l.head;
if ((def.mods.flags & STATIC) != 0) {
VarSymbol sym = def.sym;
if (trackable(sym)) {
newVar(def);
}
}
}
}
classDef = tree;
try {
// define all the static fields
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(VARDEF)) {
JCVariableDecl def = (JCVariableDecl)l.head;
if ((def.mods.flags & STATIC) != 0) {
VarSymbol sym = def.sym;
if (trackable(sym)) {
newVar(def);
}
// process all the static initializers
forEachInitializer(tree, true, def -> {
scan(def);
clearPendingExits(false);
});
// verify all static final fields got initialized
for (int i = firstadr; i < nextadr; i++) {
JCVariableDecl vardecl = vardecls[i];
VarSymbol var = vardecl.sym;
if (var.owner == classDef.sym && var.isStatic()) {
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
}
}
// define all the instance fields
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(VARDEF)) {
JCVariableDecl def = (JCVariableDecl)l.head;
if ((def.mods.flags & STATIC) == 0) {
VarSymbol sym = def.sym;
if (trackable(sym)) {
newVar(def);
}
}
}
}
// process all the static initializers
forEachInitializer(tree, true, def -> {
scan(def);
clearPendingExits(false);
});
// verify all static final fields got initialized
for (int i = firstadr; i < nextadr; i++) {
JCVariableDecl vardecl = vardecls[i];
VarSymbol var = vardecl.sym;
if (var.owner == classDef.sym && var.isStatic()) {
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
}
// process all the methods
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(METHODDEF)) {
scan(l.head);
}
}
// define all the instance fields
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(VARDEF)) {
JCVariableDecl def = (JCVariableDecl)l.head;
if ((def.mods.flags & STATIC) == 0) {
VarSymbol sym = def.sym;
if (trackable(sym)) {
newVar(def);
}
}
}
// process all the nested classes
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(CLASSDEF)) {
scan(l.head);
}
// process all the methods
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(METHODDEF)) {
scan(l.head);
}
}
// process all the nested classes
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.hasTag(CLASSDEF)) {
scan(l.head);
}
}
} finally {
pendingExits = pendingExitsPrev;
nextadr = nextadrPrev;
firstadr = firstadrPrev;
classDef = classDefPrev;
}
} finally {
lint = lintPrev;
pendingExits = pendingExitsPrev;
nextadr = nextadrPrev;
firstadr = firstadrPrev;
classDef = classDefPrev;
}
}
@ -2477,87 +2435,81 @@ public class Flow {
return;
}
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
final Bits initsPrev = new Bits(inits);
final Bits uninitsPrev = new Bits(uninits);
int nextadrPrev = nextadr;
int firstadrPrev = firstadr;
int returnadrPrev = returnadr;
Assert.check(pendingExits.isEmpty());
boolean isConstructorPrev = isConstructor;
try {
final Bits initsPrev = new Bits(inits);
final Bits uninitsPrev = new Bits(uninits);
int nextadrPrev = nextadr;
int firstadrPrev = firstadr;
int returnadrPrev = returnadr;
isConstructor = TreeInfo.isConstructor(tree);
Assert.check(pendingExits.isEmpty());
boolean isConstructorPrev = isConstructor;
try {
isConstructor = TreeInfo.isConstructor(tree);
// We only track field initialization inside constructors
if (!isConstructor) {
firstadr = nextadr;
}
// We only track field initialization inside constructors
if (!isConstructor) {
firstadr = nextadr;
}
// Mark all method parameters as DA
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
JCVariableDecl def = l.head;
scan(def);
Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
/* If we are executing the code from Gen, then there can be
* synthetic or mandated variables, ignore them.
*/
initParam(def);
}
// else we are in an instance initializer block;
// leave caught unchanged.
scan(tree.body);
// Mark all method parameters as DA
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
JCVariableDecl def = l.head;
scan(def);
Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
/* If we are executing the code from Gen, then there can be
* synthetic or mandated variables, ignore them.
*/
initParam(def);
}
// else we are in an instance initializer block;
// leave caught unchanged.
scan(tree.body);
boolean isCompactOrGeneratedRecordConstructor = (tree.sym.flags() & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
(tree.sym.flags() & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD);
if (isConstructor) {
boolean isSynthesized = (tree.sym.flags() &
GENERATEDCONSTR) != 0;
for (int i = firstadr; i < nextadr; i++) {
JCVariableDecl vardecl = vardecls[i];
VarSymbol var = vardecl.sym;
if (var.owner == classDef.sym && !var.isStatic()) {
// choose the diagnostic position based on whether
// the ctor is default(synthesized) or not
if (isSynthesized && !isCompactOrGeneratedRecordConstructor) {
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
var, Errors.VarNotInitializedInDefaultConstructor(var));
} else if (isCompactOrGeneratedRecordConstructor) {
boolean isInstanceRecordField = var.enclClass().isRecord() &&
(var.flags_field & (Flags.PRIVATE | Flags.FINAL | Flags.GENERATED_MEMBER | Flags.RECORD)) != 0 &&
var.owner.kind == TYP;
if (isInstanceRecordField) {
boolean notInitialized = !inits.isMember(var.adr);
if (notInitialized && uninits.isMember(var.adr) && tree.completesNormally) {
/* this way we indicate Lower that it should generate an initialization for this field
* in the compact constructor
*/
var.flags_field |= UNINITIALIZED_FIELD;
} else {
checkInit(TreeInfo.diagEndPos(tree.body), var);
}
boolean isCompactOrGeneratedRecordConstructor = (tree.sym.flags() & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
(tree.sym.flags() & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD);
if (isConstructor) {
boolean isSynthesized = (tree.sym.flags() &
GENERATEDCONSTR) != 0;
for (int i = firstadr; i < nextadr; i++) {
JCVariableDecl vardecl = vardecls[i];
VarSymbol var = vardecl.sym;
if (var.owner == classDef.sym && !var.isStatic()) {
// choose the diagnostic position based on whether
// the ctor is default(synthesized) or not
if (isSynthesized && !isCompactOrGeneratedRecordConstructor) {
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
var, Errors.VarNotInitializedInDefaultConstructor(var));
} else if (isCompactOrGeneratedRecordConstructor) {
boolean isInstanceRecordField = var.enclClass().isRecord() &&
(var.flags_field & (Flags.PRIVATE | Flags.FINAL | Flags.GENERATED_MEMBER | Flags.RECORD)) != 0 &&
var.owner.kind == TYP;
if (isInstanceRecordField) {
boolean notInitialized = !inits.isMember(var.adr);
if (notInitialized && uninits.isMember(var.adr) && tree.completesNormally) {
/* this way we indicate Lower that it should generate an initialization for this field
* in the compact constructor
*/
var.flags_field |= UNINITIALIZED_FIELD;
} else {
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
checkInit(TreeInfo.diagEndPos(tree.body), var);
}
} else {
checkInit(TreeInfo.diagEndPos(tree.body), var);
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
}
} else {
checkInit(TreeInfo.diagEndPos(tree.body), var);
}
}
}
clearPendingExits(true);
} finally {
inits.assign(initsPrev);
uninits.assign(uninitsPrev);
nextadr = nextadrPrev;
firstadr = firstadrPrev;
returnadr = returnadrPrev;
isConstructor = isConstructorPrev;
}
clearPendingExits(true);
} finally {
lint = lintPrev;
inits.assign(initsPrev);
uninits.assign(uninitsPrev);
nextadr = nextadrPrev;
firstadr = firstadrPrev;
returnadr = returnadrPrev;
isConstructor = isConstructorPrev;
}
}
@ -2585,21 +2537,15 @@ public class Flow {
}
public void visitVarDef(JCVariableDecl tree) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try{
boolean track = trackable(tree.sym);
if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
newVar(tree);
boolean track = trackable(tree.sym);
if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
newVar(tree);
}
if (tree.init != null) {
scanExpr(tree.init);
if (track) {
letInit(tree.pos(), tree.sym);
}
if (tree.init != null) {
scanExpr(tree.init);
if (track) {
letInit(tree.pos(), tree.sym);
}
}
} finally {
lint = lintPrev;
}
}
@ -2851,8 +2797,7 @@ public class Flow {
final Bits uninitsEnd = new Bits(uninits);
int nextadrCatch = nextadr;
if (!resourceVarDecls.isEmpty() &&
lint.isEnabled(Lint.LintCategory.TRY)) {
if (!resourceVarDecls.isEmpty()) {
for (JCVariableDecl resVar : resourceVarDecls) {
if (unrefdResources.includes(resVar.sym) && !resVar.sym.isUnnamedVariable()) {
log.warning(resVar.pos(),

View File

@ -66,7 +66,6 @@ public class MemberEnter extends JCTree.Visitor {
private final Annotate annotate;
private final Types types;
private final Names names;
private final DeferredLintHandler deferredLintHandler;
public static MemberEnter instance(Context context) {
MemberEnter instance = context.get(memberEnterKey);
@ -87,7 +86,6 @@ public class MemberEnter extends JCTree.Visitor {
types = Types.instance(context);
source = Source.instance(context);
names = Names.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
}
/** Construct method type from method signature.
@ -194,16 +192,11 @@ public class MemberEnter extends JCTree.Visitor {
}
Env<AttrContext> localEnv = methodEnv(tree, env);
deferredLintHandler.push(tree);
try {
// Compute the method type
m.type = signature(m, tree.typarams, tree.params,
tree.restype, tree.recvparam,
tree.thrown,
localEnv);
} finally {
deferredLintHandler.pop();
}
// Compute the method type
m.type = signature(m, tree.typarams, tree.params,
tree.restype, tree.recvparam,
tree.thrown,
localEnv);
if (types.isSignaturePolymorphic(m)) {
m.flags_field |= SIGNATURE_POLYMORPHIC;
@ -227,14 +220,14 @@ public class MemberEnter extends JCTree.Visitor {
enclScope.enter(m);
}
annotate.annotateLater(tree.mods.annotations, localEnv, m, tree);
annotate.annotateLater(tree.mods.annotations, localEnv, m);
// Visit the signature of the method. Note that
// TypeAnnotate doesn't descend into the body.
annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, m, tree);
annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, m);
if (tree.defaultValue != null) {
m.defaultValue = annotate.unfinishedDefaultValue(); // set it to temporary sentinel for now
annotate.annotateDefaultValueLater(tree.defaultValue, localEnv, m, tree);
annotate.annotateDefaultValueLater(tree.defaultValue, localEnv, m);
}
}
@ -263,18 +256,13 @@ public class MemberEnter extends JCTree.Visitor {
localEnv = env.dup(tree, env.info.dup());
localEnv.info.staticLevel++;
}
deferredLintHandler.push(tree);
try {
if (TreeInfo.isEnumInit(tree)) {
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
} else if (!tree.isImplicitlyTyped()) {
attr.attribType(tree.vartype, localEnv);
if (TreeInfo.isReceiverParam(tree))
checkReceiver(tree, localEnv);
}
} finally {
deferredLintHandler.pop();
if (TreeInfo.isEnumInit(tree)) {
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
} else if (!tree.isImplicitlyTyped()) {
attr.attribType(tree.vartype, localEnv);
if (TreeInfo.isReceiverParam(tree))
checkReceiver(tree, localEnv);
}
if ((tree.mods.flags & VARARGS) != 0) {
@ -315,9 +303,9 @@ public class MemberEnter extends JCTree.Visitor {
}
}
annotate.annotateLater(tree.mods.annotations, localEnv, v, tree);
annotate.annotateLater(tree.mods.annotations, localEnv, v);
if (!tree.isImplicitlyTyped()) {
annotate.queueScanTreeAndTypeAnnotate(tree.vartype, localEnv, v, tree);
annotate.queueScanTreeAndTypeAnnotate(tree.vartype, localEnv, v);
}
v.pos = tree.pos;

View File

@ -52,7 +52,6 @@ import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;
import com.sun.source.tree.ModuleTree.ModuleKind;
import com.sun.tools.javac.code.DeferredLintHandler;
import com.sun.tools.javac.code.Directive;
import com.sun.tools.javac.code.Directive.ExportsDirective;
import com.sun.tools.javac.code.Directive.ExportsFlag;
@ -141,7 +140,6 @@ public class Modules extends JCTree.Visitor {
private final Attr attr;
private final Check chk;
private final Preview preview;
private final DeferredLintHandler deferredLintHandler;
private final TypeEnvs typeEnvs;
private final Types types;
private final JavaFileManager fileManager;
@ -169,8 +167,6 @@ public class Modules extends JCTree.Visitor {
private final String moduleVersionOpt;
private final boolean sourceLauncher;
private final boolean lintOptions;
private Set<ModuleSymbol> rootModules = null;
private final Set<ModuleSymbol> warnedMissing = new HashSet<>();
@ -193,7 +189,6 @@ public class Modules extends JCTree.Visitor {
attr = Attr.instance(context);
chk = Check.instance(context);
preview = Preview.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
typeEnvs = TypeEnvs.instance(context);
moduleFinder = ModuleFinder.instance(context);
types = Types.instance(context);
@ -205,8 +200,6 @@ public class Modules extends JCTree.Visitor {
allowAccessIntoSystem = options.isUnset(Option.RELEASE);
lintOptions = !options.isLintDisabled(LintCategory.OPTIONS);
multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
ClassWriter classWriter = ClassWriter.instance(context);
classWriter.multiModuleMode = multiModuleMode;
@ -746,7 +739,6 @@ public class Modules extends JCTree.Visitor {
ModuleVisitor v = new ModuleVisitor();
JavaFileObject prev = log.useSource(tree.sourcefile);
JCModuleDecl moduleDecl = tree.getModuleDecl();
deferredLintHandler.push(moduleDecl);
try {
moduleDecl.accept(v);
@ -754,7 +746,6 @@ public class Modules extends JCTree.Visitor {
checkCyclicDependencies(moduleDecl);
} finally {
log.useSource(prev);
deferredLintHandler.pop();
msym.flags_field &= ~UNATTRIBUTED;
}
}
@ -991,13 +982,11 @@ public class Modules extends JCTree.Visitor {
UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
JCModuleDecl decl = env.toplevel.getModuleDecl();
deferredLintHandler.push(decl);
try {
decl.accept(v);
} finally {
log.useSource(prev);
deferredLintHandler.pop();
}
};
}
@ -1263,12 +1252,9 @@ public class Modules extends JCTree.Visitor {
}
observable = computeTransitiveClosure(limitMods, rootModules, null);
observable.addAll(rootModules);
if (lintOptions) {
for (ModuleSymbol msym : limitMods) {
if (!observable.contains(msym)) {
log.warning(
LintWarnings.ModuleForOptionNotFound(Option.LIMIT_MODULES, msym));
}
for (ModuleSymbol msym : limitMods) {
if (!observable.contains(msym)) {
log.warning(LintWarnings.ModuleForOptionNotFound(Option.LIMIT_MODULES, msym));
}
}
}
@ -1721,10 +1707,7 @@ public class Modules extends JCTree.Visitor {
}
if (!unknownModules.contains(msym)) {
if (lintOptions) {
log.warning(
LintWarnings.ModuleForOptionNotFound(Option.ADD_EXPORTS, msym));
}
log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_EXPORTS, msym));
unknownModules.add(msym);
}
return false;
@ -1760,9 +1743,7 @@ public class Modules extends JCTree.Visitor {
ModuleSymbol msym = syms.enterModule(names.fromString(sourceName));
if (!allModules.contains(msym)) {
if (lintOptions) {
log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, msym));
}
log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, msym));
continue;
}
@ -1780,9 +1761,7 @@ public class Modules extends JCTree.Visitor {
continue;
targetModule = syms.enterModule(names.fromString(targetName));
if (!allModules.contains(targetModule)) {
if (lintOptions) {
log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, targetModule));
}
log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, targetModule));
continue;
}
}

View File

@ -45,6 +45,7 @@ import java.util.stream.Stream;
import com.sun.tools.javac.code.Directive;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symtab;
@ -57,6 +58,7 @@ import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
@ -67,6 +69,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.Lint.LintCategory.THIS_ESCAPE;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
import static com.sun.tools.javac.util.Position.NOPOS;
/**
* Looks for possible 'this' escapes and generates corresponding warnings.
@ -156,7 +159,7 @@ public class ThisEscapeAnalyzer extends TreeScanner {
private final Types types;
private final Resolve rs;
private final Log log;
private Lint lint;
private final LintMapper lintMapper;
// These fields are scoped to the entire compilation unit
@ -168,10 +171,6 @@ public class ThisEscapeAnalyzer extends TreeScanner {
*/
private final Map<Symbol, MethodInfo> methodMap = new LinkedHashMap<>();
/** Contains symbols of fields and constructors that have warnings suppressed.
*/
private final Set<Symbol> suppressed = new HashSet<>();
/** Contains classes whose outer instance (if any) is non-public.
*/
private final Set<ClassSymbol> nonPublicOuters = new HashSet<>();
@ -231,7 +230,7 @@ public class ThisEscapeAnalyzer extends TreeScanner {
syms = Symtab.instance(context);
types = Types.instance(context);
rs = Resolve.instance(context);
lint = Lint.instance(context);
lintMapper = LintMapper.instance(context);
}
//
@ -262,8 +261,8 @@ public class ThisEscapeAnalyzer extends TreeScanner {
Assert.check(checkInvariants(false, false));
Assert.check(methodMap.isEmpty()); // we are not prepared to be used more than once
// Short circuit if warnings are totally disabled
if (!lint.isEnabled(THIS_ESCAPE))
// Short circuit if this calculation is unnecessary
if (!lintMapper.lintAt(env.toplevel.sourcefile, env.tree.pos()).get().isEnabled(THIS_ESCAPE))
return;
// Determine which packages are exported by the containing module, if any.
@ -278,11 +277,9 @@ public class ThisEscapeAnalyzer extends TreeScanner {
// Build a mapping from symbols of methods to their declarations.
// Classify all ctors and methods as analyzable and/or invokable.
// Track which constructors and fields have warnings suppressed.
// Record classes whose outer instance (if any) is non-public.
new TreeScanner() {
private Lint lint = ThisEscapeAnalyzer.this.lint;
private JCClassDecl currentClass;
private boolean nonPublicOuter;
@ -290,8 +287,6 @@ public class ThisEscapeAnalyzer extends TreeScanner {
public void visitClassDef(JCClassDecl tree) {
JCClassDecl currentClassPrev = currentClass;
boolean nonPublicOuterPrev = nonPublicOuter;
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try {
currentClass = tree;
@ -306,57 +301,29 @@ public class ThisEscapeAnalyzer extends TreeScanner {
} finally {
currentClass = currentClassPrev;
nonPublicOuter = nonPublicOuterPrev;
lint = lintPrev;
}
}
@Override
public void visitVarDef(JCVariableDecl tree) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try {
// Track warning suppression of fields
if (tree.sym.owner.kind == TYP && !lint.isEnabled(THIS_ESCAPE))
suppressed.add(tree.sym);
// Recurse
super.visitVarDef(tree);
} finally {
lint = lintPrev;
}
}
@Override
public void visitMethodDef(JCMethodDecl tree) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try {
// Track warning suppression of constructors
if (TreeInfo.isConstructor(tree) && !lint.isEnabled(THIS_ESCAPE))
suppressed.add(tree.sym);
// Gather some useful info
boolean constructor = TreeInfo.isConstructor(tree);
boolean extendableClass = currentClassIsExternallyExtendable();
boolean nonPrivate = (tree.sym.flags() & (Flags.PUBLIC | Flags.PROTECTED)) != 0;
boolean finalish = (tree.mods.flags & (Flags.STATIC | Flags.PRIVATE | Flags.FINAL)) != 0;
// Gather some useful info
boolean constructor = TreeInfo.isConstructor(tree);
boolean extendableClass = currentClassIsExternallyExtendable();
boolean nonPrivate = (tree.sym.flags() & (Flags.PUBLIC | Flags.PROTECTED)) != 0;
boolean finalish = (tree.mods.flags & (Flags.STATIC | Flags.PRIVATE | Flags.FINAL)) != 0;
// Determine if this is a constructor we should analyze
boolean analyzable = extendableClass && constructor && nonPrivate;
// Determine if this is a constructor we should analyze
boolean analyzable = extendableClass && constructor && nonPrivate;
// Determine if it's safe to "invoke" the method in an analysis (i.e., it can't be overridden)
boolean invokable = !extendableClass || constructor || finalish;
// Determine if it's safe to "invoke" the method in an analysis (i.e., it can't be overridden)
boolean invokable = !extendableClass || constructor || finalish;
// Add this method or constructor to our map
methodMap.put(tree.sym, new MethodInfo(currentClass, tree, constructor, analyzable, invokable));
// Add this method or constructor to our map
methodMap.put(tree.sym, new MethodInfo(currentClass, tree, constructor, analyzable, invokable));
// Recurse
super.visitMethodDef(tree);
} finally {
lint = lintPrev;
}
// Recurse
super.visitMethodDef(tree);
}
// Determines if the current class could be extended in some other package/module
@ -401,7 +368,7 @@ public class ThisEscapeAnalyzer extends TreeScanner {
for (Warning warning : warningList) {
LintWarning key = LintWarnings.PossibleThisEscape;
for (StackFrame frame : warning.stack) {
log.warning(frame.site.pos(), key);
log.warning(frame.warningPos(), key);
key = LintWarnings.PossibleThisEscapeLocation;
}
}
@ -1746,9 +1713,16 @@ public class ThisEscapeAnalyzer extends TreeScanner {
this.suppressible = initializer != null || (method.constructor && method.declaringClass == targetClass);
}
DiagnosticPosition warningPos() {
return site.pos().withLintPosition(NOPOS); // disable normal Lint suppression
}
Lint lint() {
return lintMapper.lintAt(topLevelEnv.toplevel.sourcefile, site.pos()).get();
}
boolean isSuppressed() {
return suppressible &&
suppressed.contains(initializer instanceof JCVariableDecl v ? v.sym : method.declaration.sym);
return suppressible && !lint().isEnabled(THIS_ESCAPE);
}
int comparePos(StackFrame that) {

View File

@ -34,7 +34,6 @@ import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Directive.ExportsDirective;
import com.sun.tools.javac.code.Directive.RequiresDirective;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Scope.ImportFilter;
import com.sun.tools.javac.code.Scope.NamedImportScope;
import com.sun.tools.javac.code.Scope.StarImportScope;
@ -108,8 +107,6 @@ public class TypeEnter implements Completer {
private final Annotate annotate;
private final TypeAnnotations typeAnnotations;
private final Types types;
private final DeferredLintHandler deferredLintHandler;
private final Lint lint;
private final TypeEnvs typeEnvs;
private final Dependencies dependencies;
@ -135,8 +132,6 @@ public class TypeEnter implements Completer {
annotate = Annotate.instance(context);
typeAnnotations = TypeAnnotations.instance(context);
types = Types.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
lint = Lint.instance(context);
typeEnvs = TypeEnvs.instance(context);
dependencies = Dependencies.instance(context);
Source source = Source.instance(context);
@ -274,7 +269,6 @@ public class TypeEnter implements Completer {
queue.add(env);
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
deferredLintHandler.push(tree);
try {
dependencies.push(env.enclClass.sym, phaseName);
runPhase(env);
@ -282,7 +276,6 @@ public class TypeEnter implements Completer {
chk.completionError(tree.pos(), ex);
} finally {
dependencies.pop();
deferredLintHandler.pop();
log.useSource(prev);
}
}
@ -351,8 +344,6 @@ public class TypeEnter implements Completer {
ImportFilter prevStaticImportFilter = staticImportFilter;
ImportFilter prevTypeImportFilter = typeImportFilter;
deferredLintHandler.pushImmediate(lint);
Lint prevLint = chk.setLint(lint);
Env<AttrContext> prevEnv = this.env;
try {
this.env = env;
@ -376,20 +367,13 @@ public class TypeEnter implements Completer {
handleImports(tree.getImports());
if (decl != null) {
deferredLintHandler.push(decl);
try {
//check @Deprecated:
markDeprecated(decl.sym, decl.mods.annotations, env);
} finally {
deferredLintHandler.pop();
}
//check for @Deprecated annotations
markDeprecated(decl.sym, decl.mods.annotations, env);
// process module annotations
annotate.annotateLater(decl.mods.annotations, env, env.toplevel.modle, decl);
annotate.annotateLater(decl.mods.annotations, env, env.toplevel.modle);
}
} finally {
this.env = prevEnv;
chk.setLint(prevLint);
deferredLintHandler.pop();
this.staticImportFilter = prevStaticImportFilter;
this.typeImportFilter = prevTypeImportFilter;
}
@ -422,7 +406,7 @@ public class TypeEnter implements Completer {
}
}
// process package annotations
annotate.annotateLater(tree.annotations, env, env.toplevel.packge, tree);
annotate.annotateLater(tree.annotations, env, env.toplevel.packge);
}
private void doImport(JCImport tree, boolean fromModuleImport) {
@ -914,9 +898,9 @@ public class TypeEnter implements Completer {
Env<AttrContext> baseEnv = baseEnv(tree, env);
if (tree.extending != null)
annotate.queueScanTreeAndTypeAnnotate(tree.extending, baseEnv, sym, tree);
annotate.queueScanTreeAndTypeAnnotate(tree.extending, baseEnv, sym);
for (JCExpression impl : tree.implementing)
annotate.queueScanTreeAndTypeAnnotate(impl, baseEnv, sym, tree);
annotate.queueScanTreeAndTypeAnnotate(impl, baseEnv, sym);
annotate.flush();
attribSuperTypes(env, baseEnv);
@ -931,11 +915,11 @@ public class TypeEnter implements Completer {
chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
}
annotate.annotateLater(tree.mods.annotations, baseEnv, sym, tree);
annotate.annotateLater(tree.mods.annotations, baseEnv, sym);
attr.attribTypeVariables(tree.typarams, baseEnv, false);
for (JCTypeParameter tp : tree.typarams)
annotate.queueScanTreeAndTypeAnnotate(tp, baseEnv, sym, tree);
annotate.queueScanTreeAndTypeAnnotate(tp, baseEnv, sym);
// check that no package exists with same fully qualified name,
// but admit classes in the unnamed package which have the same

View File

@ -92,7 +92,7 @@ public abstract class BaseFileManager implements JavaFileManager {
options = Options.instance(context);
// Initialize locations
locations.update(log, lint, FSInfo.instance(context));
locations.update(log, FSInfo.instance(context));
// Apply options
options.whenReady(this::applyOptions);

View File

@ -77,12 +77,11 @@ import javax.tools.StandardJavaFileManager;
import javax.tools.StandardJavaFileManager.PathFactory;
import javax.tools.StandardLocation;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
import jdk.internal.jmod.JmodFile;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.ListBuffer;
@ -123,11 +122,6 @@ public class Locations {
*/
private FSInfo fsInfo;
/**
* The root {@link Lint} instance.
*/
private Lint lint;
private ModuleNameReader moduleNameReader;
private PathFactory pathFactory = Paths::get;
@ -168,9 +162,8 @@ public class Locations {
}
}
void update(Log log, Lint lint, FSInfo fsInfo) {
void update(Log log, FSInfo fsInfo) {
this.log = log;
this.lint = lint;
this.fsInfo = fsInfo;
}
@ -221,7 +214,7 @@ public class Locations {
try {
entries.add(getPath(s));
} catch (IllegalArgumentException e) {
lint.logIfEnabled(LintWarnings.InvalidPath(s));
log.warning(LintWarnings.InvalidPath(s));
}
}
}
@ -316,7 +309,7 @@ public class Locations {
private void addDirectory(Path dir, boolean warn) {
if (!Files.isDirectory(dir)) {
if (warn) {
lint.logIfEnabled(LintWarnings.DirPathElementNotFound(dir));
log.warning(LintWarnings.DirPathElementNotFound(dir));
}
return;
}
@ -361,7 +354,7 @@ public class Locations {
if (!fsInfo.exists(file)) {
/* No such file or directory exists */
if (warn) {
lint.logIfEnabled(LintWarnings.PathElementNotFound(file));
log.warning(LintWarnings.PathElementNotFound(file));
}
super.add(file);
return;
@ -383,12 +376,12 @@ public class Locations {
try {
FileSystems.newFileSystem(file, (ClassLoader)null).close();
if (warn) {
lint.logIfEnabled(LintWarnings.UnexpectedArchiveFile(file));
log.warning(LintWarnings.UnexpectedArchiveFile(file));
}
} catch (IOException | ProviderNotFoundException e) {
// FIXME: include e.getLocalizedMessage in warning
if (warn) {
lint.logIfEnabled(LintWarnings.InvalidArchiveFile(file));
log.warning(LintWarnings.InvalidArchiveFile(file));
}
return;
}
@ -1651,7 +1644,7 @@ public class Locations {
void add(Map<String, List<Path>> map, Path prefix, Path suffix) {
if (!Files.isDirectory(prefix)) {
lint.logIfEnabled(Files.exists(prefix) ?
log.warning(Files.exists(prefix) ?
LintWarnings.DirPathElementNotDirectory(prefix) :
LintWarnings.DirPathElementNotFound(prefix));
return;

View File

@ -51,7 +51,6 @@ import com.sun.tools.javac.comp.Annotate;
import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Directive.*;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symtab;
@ -139,9 +138,6 @@ public class ClassReader {
/** The symbol table. */
Symtab syms;
/** The root Lint config. */
Lint lint;
Types types;
/** The name table. */
@ -303,8 +299,6 @@ public class ClassReader {
typevars = WriteableScope.create(syms.noSymbol);
lint = Lint.instance(context);
initAttributeReaders();
}
@ -854,8 +848,7 @@ public class ClassReader {
if (!warnedAttrs.contains(name)) {
JavaFileObject prev = log.useSource(currentClassFile);
try {
lint.logIfEnabled(
LintWarnings.FutureAttr(name, version.major, version.minor, majorVersion, minorVersion));
log.warning(LintWarnings.FutureAttr(name, version.major, version.minor, majorVersion, minorVersion));
} finally {
log.useSource(prev);
}
@ -1609,7 +1602,7 @@ public class ClassReader {
} else if (parameterAnnotations.length != numParameters) {
//the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations
//provide annotations for a different number of parameters, ignore:
lint.logIfEnabled(LintWarnings.RuntimeVisibleInvisibleParamAnnotationsMismatch(currentClassFile));
log.warning(LintWarnings.RuntimeVisibleInvisibleParamAnnotationsMismatch(currentClassFile));
for (int pnum = 0; pnum < numParameters; pnum++) {
readAnnotations();
}
@ -2075,9 +2068,9 @@ public class ClassReader {
JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
try {
if (failure == null) {
lint.logIfEnabled(LintWarnings.AnnotationMethodNotFound(container, name));
log.warning(LintWarnings.AnnotationMethodNotFound(container, name));
} else {
lint.logIfEnabled(LintWarnings.AnnotationMethodNotFoundReason(container,
log.warning(LintWarnings.AnnotationMethodNotFoundReason(container,
name,
failure.getDetailValue()));//diagnostic, if present
}
@ -2954,7 +2947,7 @@ public class ClassReader {
private void dropParameterAnnotations() {
parameterAnnotations = null;
lint.logIfEnabled(LintWarnings.RuntimeInvisibleParameterAnnotations(currentClassFile));
log.warning(LintWarnings.RuntimeInvisibleParameterAnnotations(currentClassFile));
}
/**
* Creates the parameter at the position {@code mpIndex} in the parameter list of the owning method.

View File

@ -52,7 +52,6 @@ import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.file.JavacFileManager;
@ -503,12 +502,9 @@ public class Arguments {
}
} else {
// single-module or legacy mode
boolean lintPaths = !options.isLintDisabled(LintCategory.PATH);
if (lintPaths) {
Path outDirParent = outDir.getParent();
if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) {
log.warning(LintWarnings.OutdirIsInExplodedModule(outDir));
}
Path outDirParent = outDir.getParent();
if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) {
log.warning(LintWarnings.OutdirIsInExplodedModule(outDir));
}
}
}
@ -576,15 +572,14 @@ public class Arguments {
reportDiag(Errors.SourcepathModulesourcepathConflict);
}
boolean lintOptions = !options.isLintDisabled(LintCategory.OPTIONS);
if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
if (source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
if (fm instanceof BaseFileManager baseFileManager) {
if (source.compareTo(Source.JDK8) <= 0) {
if (baseFileManager.isDefaultBootClassPath())
if (baseFileManager.isDefaultBootClassPath()) {
log.warning(LintWarnings.SourceNoBootclasspath(source.name, releaseNote(source, targetString)));
} else {
if (baseFileManager.isDefaultSystemModulesPath())
log.warning(LintWarnings.SourceNoSystemModulesPath(source.name, releaseNote(source, targetString)));
}
} else if (baseFileManager.isDefaultSystemModulesPath()) {
log.warning(LintWarnings.SourceNoSystemModulesPath(source.name, releaseNote(source, targetString)));
}
}
}
@ -593,14 +588,14 @@ public class Arguments {
if (source.compareTo(Source.MIN) < 0) {
log.error(Errors.OptionRemovedSource(source.name, Source.MIN.name));
} else if (source == Source.MIN && lintOptions) {
} else if (source == Source.MIN) {
log.warning(LintWarnings.OptionObsoleteSource(source.name));
obsoleteOptionFound = true;
}
if (target.compareTo(Target.MIN) < 0) {
log.error(Errors.OptionRemovedTarget(target, Target.MIN));
} else if (target == Target.MIN && lintOptions) {
} else if (target == Target.MIN) {
log.warning(LintWarnings.OptionObsoleteTarget(target));
obsoleteOptionFound = true;
}
@ -634,7 +629,7 @@ public class Arguments {
log.error(Errors.ProcessorpathNoProcessormodulepath);
}
if (obsoleteOptionFound && lintOptions) {
if (obsoleteOptionFound) {
log.warning(LintWarnings.OptionObsoleteSuppression);
}
@ -645,7 +640,7 @@ public class Arguments {
validateLimitModules(sv);
validateDefaultModuleForCreatedFiles(sv);
if (lintOptions && options.isSet(Option.ADD_OPENS)) {
if (options.isSet(Option.ADD_OPENS)) {
log.warning(LintWarnings.AddopensIgnored);
}

View File

@ -258,6 +258,10 @@ public class JavaCompiler {
*/
protected JNIWriter jniWriter;
/** The Lint mapper.
*/
protected LintMapper lintMapper;
/** The module for the symbol table entry phases.
*/
protected Enter enter;
@ -384,6 +388,7 @@ public class JavaCompiler {
names = Names.instance(context);
log = Log.instance(context);
lintMapper = LintMapper.instance(context);
diagFactory = JCDiagnostic.Factory.instance(context);
finder = ClassFinder.instance(context);
reader = ClassReader.instance(context);
@ -575,6 +580,7 @@ public class JavaCompiler {
/** The number of errors reported so far.
*/
public int errorCount() {
log.reportOutstandingWarnings();
if (werror && log.nerrors == 0 && log.nwarnings > 0) {
log.error(Errors.WarningsAndWerror);
}
@ -625,6 +631,7 @@ public class JavaCompiler {
private JCCompilationUnit parse(JavaFileObject filename, CharSequence content, boolean silent) {
long msec = now();
JCCompilationUnit tree = make.TopLevel(List.nil());
lintMapper.startParsingFile(filename);
if (content != null) {
if (verbose) {
log.printVerbose("parsing.started", filename);
@ -644,6 +651,7 @@ public class JavaCompiler {
}
tree.sourcefile = filename;
lintMapper.finishParsingFile(tree);
if (content != null && !taskListener.isEmpty() && !silent) {
TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree);
@ -1843,6 +1851,7 @@ public class JavaCompiler {
else
log.warning(Warnings.ProcUseProcOrImplicit);
}
log.reportOutstandingWarnings();
log.reportOutstandingNotes();
if (log.compressedOutput) {
log.note(Notes.CompressedDiags);
@ -1916,6 +1925,7 @@ public class JavaCompiler {
attr = null;
chk = null;
gen = null;
lintMapper = null;
flow = null;
transTypes = null;
lower = null;

View File

@ -25,8 +25,6 @@
package com.sun.tools.javac.parser;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Source.Feature;
@ -83,7 +81,7 @@ public class JavaTokenizer extends UnicodeReader {
/**
* The log to be used for error reporting. Copied from scanner factory.
*/
private final Log log;
protected final Log log;
/**
* The token factory. Copied from scanner factory.
@ -135,13 +133,6 @@ public class JavaTokenizer extends UnicodeReader {
*/
protected boolean hasEscapeSequences;
/**
* The set of lint options currently in effect. It is initialized
* from the context, and then is set/reset as needed by Attr as it
* visits all the various parts of the trees during attribution.
*/
protected final Lint lint;
/**
* Construct a Java token scanner from the input character buffer.
*
@ -168,7 +159,6 @@ public class JavaTokenizer extends UnicodeReader {
this.source = fac.source;
this.preview = fac.preview;
this.enableLineDocComments = fac.enableLineDocComments;
this.lint = fac.lint;
this.sb = new StringBuilder(256);
}
@ -205,17 +195,6 @@ public class JavaTokenizer extends UnicodeReader {
errPos = pos;
}
/**
* Report a warning at the given position using the provided arguments.
*
* @param pos position in input buffer.
* @param key error key to report.
*/
protected void lexWarning(int pos, JCDiagnostic.LintWarning key) {
DiagnosticPosition dp = new SimpleDiagnosticPosition(pos) ;
log.warning(dp, key);
}
/**
* Add a character to the literal buffer.
*
@ -1060,17 +1039,12 @@ public class JavaTokenizer extends UnicodeReader {
// If a text block.
if (isTextBlock) {
// Verify that the incidental indentation is consistent.
if (lint.isEnabled(LintCategory.TEXT_BLOCKS)) {
Set<TextBlockSupport.WhitespaceChecks> checks =
TextBlockSupport.checkWhitespace(string);
if (checks.contains(TextBlockSupport.WhitespaceChecks.INCONSISTENT)) {
lexWarning(pos,
LintWarnings.InconsistentWhiteSpaceIndentation);
}
if (checks.contains(TextBlockSupport.WhitespaceChecks.TRAILING)) {
lexWarning(pos,
LintWarnings.TrailingWhiteSpaceWillBeRemoved);
}
Set<TextBlockSupport.WhitespaceChecks> checks = TextBlockSupport.checkWhitespace(string);
if (checks.contains(TextBlockSupport.WhitespaceChecks.INCONSISTENT)) {
log.warning(pos, LintWarnings.InconsistentWhiteSpaceIndentation);
}
if (checks.contains(TextBlockSupport.WhitespaceChecks.TRAILING)) {
log.warning(pos, LintWarnings.TrailingWhiteSpaceWillBeRemoved);
}
// Remove incidental indentation.
try {

View File

@ -116,8 +116,6 @@ public class JavacParser implements Parser {
/** A map associating "other nearby documentation comments"
* with the preferred documentation comment for a declaration. */
protected Map<Comment, List<Comment>> danglingComments = new HashMap<>();
/** Handler for deferred diagnostics. */
protected final DeferredLintHandler deferredLintHandler;
// Because of javac's limited lookahead, some contexts are ambiguous in
// the presence of type annotations even though they are not ambiguous
@ -190,7 +188,6 @@ public class JavacParser implements Parser {
this.names = fac.names;
this.source = fac.source;
this.preview = fac.preview;
this.deferredLintHandler = fac.deferredLintHandler;
this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
this.keepDocComments = keepDocComments;
this.parseModuleInfo = parseModuleInfo;
@ -216,7 +213,6 @@ public class JavacParser implements Parser {
this.names = parser.names;
this.source = parser.source;
this.preview = parser.preview;
this.deferredLintHandler = parser.deferredLintHandler;
this.allowStringFolding = parser.allowStringFolding;
this.keepDocComments = parser.keepDocComments;
this.parseModuleInfo = false;
@ -591,8 +587,7 @@ public class JavacParser implements Parser {
* 4. When the tree node for the declaration is finally
* available, and the primary comment, if any,
* is "attached", (in {@link #attach}) any related
* dangling comments are also attached to the tree node
* by registering them using the {@link #deferredLintHandler}.
* dangling comments are reported to the log as warnings.
* 5. (Later) Warnings may be generated for the dangling
* comments, subject to the {@code -Xlint} and
* {@code @SuppressWarnings}.
@ -653,32 +648,22 @@ public class JavacParser implements Parser {
void reportDanglingComments(JCTree tree, Comment dc) {
var list = danglingComments.remove(dc);
if (list != null) {
deferredLintHandler.push(tree);
try {
list.forEach(this::reportDanglingDocComment);
} finally {
deferredLintHandler.pop();
}
list.forEach(c -> reportDanglingDocComment(tree, c));
}
}
/**
* Reports an individual dangling comment using the {@link #deferredLintHandler}.
* Reports an individual dangling comment as a warning to the log.
* The comment may or not may generate an actual diagnostic, depending on
* the settings for {@code -Xlint} and/or {@code @SuppressWarnings}.
*
* @param c the comment
*/
void reportDanglingDocComment(Comment c) {
void reportDanglingDocComment(JCTree tree, Comment c) {
var pos = c.getPos();
if (pos != null) {
deferredLintHandler.report(lint -> {
if (lint.isEnabled(Lint.LintCategory.DANGLING_DOC_COMMENTS) &&
!shebang(c, pos)) {
log.warning(
pos, LintWarnings.DanglingDocComment);
}
});
if (pos != null && !shebang(c, pos)) {
pos = pos.withLintPosition(tree.getStartPosition());
S.lintWarning(pos, LintWarnings.DanglingDocComment);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -28,6 +28,8 @@ package com.sun.tools.javac.parser;
import java.util.Queue;
import com.sun.tools.javac.parser.Tokens.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.Position.LineMap;
/**
@ -103,4 +105,12 @@ public interface Lexer {
* token.
*/
Queue<Comment> getDocComments();
/**
* Report a warning that is subject to possible suppression by {@code @SuppressWarnings}.
*
* @param pos the lexical position at which the warning occurs
* @param key the warning to report
*/
void lintWarning(DiagnosticPosition pos, LintWarning key);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -28,7 +28,6 @@ package com.sun.tools.javac.parser;
import java.util.Locale;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.DeferredLintHandler;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Source;
@ -70,7 +69,6 @@ public class ParserFactory {
final Options options;
final ScannerFactory scannerFactory;
final Locale locale;
final DeferredLintHandler deferredLintHandler;
private final JavacTrees trees;
@ -88,7 +86,6 @@ public class ParserFactory {
this.options = Options.instance(context);
this.scannerFactory = ScannerFactory.instance(context);
this.locale = context.get(Locale.class);
this.deferredLintHandler = DeferredLintHandler.instance(context);
this.trees = JavacTrees.instance(context);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -31,6 +31,8 @@ import java.util.List;
import java.util.ArrayList;
import java.util.Queue;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.Position.LineMap;
import static com.sun.tools.javac.parser.Tokens.*;
@ -150,6 +152,11 @@ public class Scanner implements Lexer {
return docComments;
}
@Override
public void lintWarning(DiagnosticPosition pos, LintWarning key) {
tokenizer.log.warning(pos, key);
}
public int errPos() {
return tokenizer.errPos();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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,7 +27,6 @@ package com.sun.tools.javac.parser;
import java.nio.CharBuffer;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.main.Option;
@ -62,7 +61,6 @@ public class ScannerFactory {
final Source source;
final Preview preview;
final Tokens tokens;
final Lint lint;
final boolean enableLineDocComments;
/** Create a new scanner factory. */
@ -74,7 +72,6 @@ public class ScannerFactory {
this.source = Source.instance(context);
this.preview = Preview.instance(context);
this.tokens = Tokens.instance(context);
this.lint = Lint.instance(context);
var options = Options.instance(context);
this.enableLineDocComments = !options.isSet(Option.DISABLE_LINE_DOC_COMMENTS);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
@ -30,6 +30,7 @@ import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCErroneous;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.Error;
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Position.LineMap;
@ -167,10 +168,9 @@ public class VirtualParser extends JavacParser {
return S.getLineMap();
}
public void commit() {
for (int i = 0 ; i < offset ; i++) {
S.nextToken(); // advance underlying lexer until position matches
}
@Override
public void lintWarning(DiagnosticPosition pos, LintWarning key) {
// ignore
}
}

View File

@ -51,7 +51,6 @@ import javax.tools.JavaFileManager.Location;
import static javax.tools.StandardLocation.SOURCE_OUTPUT;
import static javax.tools.StandardLocation.CLASS_OUTPUT;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symtab;
@ -62,7 +61,6 @@ import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.main.Option;
@ -338,7 +336,6 @@ public class JavacFiler implements Filer, Closeable {
JavaFileManager fileManager;
JavacElements elementUtils;
Log log;
Lint lint;
Modules modules;
Names names;
Symtab syms;
@ -421,8 +418,6 @@ public class JavacFiler implements Filer, Closeable {
aggregateGeneratedClassNames = new LinkedHashSet<>();
initialClassNames = new LinkedHashSet<>();
lint = Lint.instance(context);
Options options = Options.instance(context);
defaultTargetModule = options.get(Option.DEFAULT_MODULE_FOR_CREATED_FILES);
@ -486,14 +481,12 @@ public class JavacFiler implements Filer, Closeable {
private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name, Element... originatingElements) throws IOException {
Assert.checkNonNull(mod);
if (lint.isEnabled(PROCESSING)) {
int periodIndex = name.lastIndexOf(".");
if (periodIndex != -1) {
String base = name.substring(periodIndex);
String extn = (isSourceFile ? ".java" : ".class");
if (base.equals(extn))
log.warning(LintWarnings.ProcSuspiciousClassName(name, extn));
}
int periodIndex = name.lastIndexOf(".");
if (periodIndex != -1) {
String base = name.substring(periodIndex);
String extn = (isSourceFile ? ".java" : ".class");
if (base.equals(extn))
log.warning(LintWarnings.ProcSuspiciousClassName(name, extn));
}
checkNameAndExistence(mod, name, isSourceFile);
Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT);
@ -707,7 +700,7 @@ public class JavacFiler implements Filer, Closeable {
private void checkName(String name, boolean allowUnnamedPackageInfo) throws FilerException {
if (!SourceVersion.isName(name) && !isPackageInfo(name, allowUnnamedPackageInfo)) {
lint.logIfEnabled(LintWarnings.ProcIllegalFileName(name));
log.warning(LintWarnings.ProcIllegalFileName(name));
throw new FilerException("Illegal name " + name);
}
}
@ -735,11 +728,11 @@ public class JavacFiler implements Filer, Closeable {
initialClassNames.contains(typename) ||
containedInInitialInputs(typename);
if (alreadySeen) {
lint.logIfEnabled(LintWarnings.ProcTypeRecreate(typename));
log.warning(LintWarnings.ProcTypeRecreate(typename));
throw new FilerException("Attempt to recreate a file for type " + typename);
}
if (existing != null) {
lint.logIfEnabled(LintWarnings.ProcTypeAlreadyExists(typename));
log.warning(LintWarnings.ProcTypeAlreadyExists(typename));
}
if (!mod.isUnnamed() && !typename.contains(".")) {
throw new FilerException("Attempt to create a type in unnamed package of a named module: " + typename);
@ -768,7 +761,7 @@ public class JavacFiler implements Filer, Closeable {
*/
private void checkFileReopening(FileObject fileObject, boolean forWriting) throws FilerException {
if (isInFileObjectHistory(fileObject, forWriting)) {
lint.logIfEnabled(LintWarnings.ProcFileReopening(fileObject.getName()));
log.warning(LintWarnings.ProcFileReopening(fileObject.getName()));
throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
}
if (forWriting)

View File

@ -123,7 +123,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
private final Modules modules;
private final Types types;
private final Annotate annotate;
private final Lint lint;
/**
* Holds relevant state history of which processors have been
@ -206,7 +205,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
printProcessorInfo = options.isSet(Option.XPRINTPROCESSORINFO);
printRounds = options.isSet(Option.XPRINTROUNDS);
verbose = options.isSet(Option.VERBOSE);
lint = Lint.instance(context);
compiler = JavaCompiler.instance(context);
if (options.isSet(Option.PROC, "only") || options.isSet(Option.XPRINT)) {
compiler.shouldStopPolicyIfNoError = CompileState.PROCESS;
@ -626,7 +624,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
private Set<String> supportedOptionNames;
ProcessorState(Processor p, Log log, Source source, DeferredCompletionFailureHandler dcfh,
boolean allowModules, ProcessingEnvironment env, Lint lint) {
boolean allowModules, ProcessingEnvironment env) {
processor = p;
contributed = false;
@ -647,10 +645,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
boolean patternAdded = supportedAnnotationStrings.add(annotationPattern);
supportedAnnotationPatterns.
add(importStringToPattern(allowModules, annotationPattern,
processor, log, lint));
add(importStringToPattern(allowModules, annotationPattern, processor, log));
if (!patternAdded) {
lint.logIfEnabled(LintWarnings.ProcDuplicateSupportedAnnotation(annotationPattern,
log.warning(LintWarnings.ProcDuplicateSupportedAnnotation(annotationPattern,
p.getClass().getName()));
}
}
@ -663,7 +660,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
// and "foo.bar.*".
if (supportedAnnotationPatterns.contains(MatchingUtils.validImportStringToPattern("*")) &&
supportedAnnotationPatterns.size() > 1) {
lint.logIfEnabled(LintWarnings.ProcRedundantTypesWithWildcard(p.getClass().getName()));
log.warning(LintWarnings.ProcRedundantTypesWithWildcard(p.getClass().getName()));
}
supportedOptionNames = new LinkedHashSet<>();
@ -671,8 +668,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
if (checkOptionName(optionName, log)) {
boolean optionAdded = supportedOptionNames.add(optionName);
if (!optionAdded) {
lint.logIfEnabled(LintWarnings.ProcDuplicateOptionName(optionName,
p.getClass().getName()));
log.warning(LintWarnings.ProcDuplicateOptionName(optionName, p.getClass().getName()));
}
}
}
@ -759,8 +755,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
ProcessorState ps = new ProcessorState(psi.processorIterator.next(),
log, source, dcfh,
Feature.MODULES.allowedInSource(source),
JavacProcessingEnvironment.this,
lint);
JavacProcessingEnvironment.this);
psi.procStateList.add(ps);
return ps;
} else
@ -888,7 +883,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
unmatchedAnnotations.remove("");
if (lint.isEnabled(PROCESSING) && unmatchedAnnotations.size() > 0) {
if (unmatchedAnnotations.size() > 0) {
// Remove annotations processed by javac
unmatchedAnnotations.keySet().removeAll(platformAnnotations);
if (unmatchedAnnotations.size() > 0) {
@ -1649,7 +1644,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
* regex matching that string. If the string is not a valid
* import-style string, return a regex that won't match anything.
*/
private static Pattern importStringToPattern(boolean allowModules, String s, Processor p, Log log, Lint lint) {
private static Pattern importStringToPattern(boolean allowModules, String s, Processor p, Log log) {
String module;
String pkg;
int slash = s.indexOf('/');
@ -1662,7 +1657,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
} else {
String moduleName = s.substring(0, slash);
if (!SourceVersion.isName(moduleName)) {
return warnAndNoMatches(s, p, log, lint);
return warnAndNoMatches(s, p, log);
}
module = Pattern.quote(moduleName + "/");
// And warn if module is specified if modules aren't supported, conditional on -Xlint:proc?
@ -1671,12 +1666,12 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
if (MatchingUtils.isValidImportString(pkg)) {
return Pattern.compile(module + MatchingUtils.validImportStringToPatternString(pkg));
} else {
return warnAndNoMatches(s, p, log, lint);
return warnAndNoMatches(s, p, log);
}
}
private static Pattern warnAndNoMatches(String s, Processor p, Log log, Lint lint) {
lint.logIfEnabled(LintWarnings.ProcMalformedSupportedString(s, p.getClass().getName()));
private static Pattern warnAndNoMatches(String s, Processor p, Log log) {
log.warning(LintWarnings.ProcMalformedSupportedString(s, p.getClass().getName()));
return noMatches; // won't match any valid identifier
}

View File

@ -1600,6 +1600,7 @@ compiler.err.multi-module.outdir.cannot.be.exploded.module=\
# 0: path
# lint: path
# flags: default-enabled
compiler.warn.outdir.is.in.exploded.module=\
the output directory is within an exploded module: {0}
@ -1924,19 +1925,19 @@ compiler.warn.incubating.modules=\
# 0: symbol, 1: symbol
# lint: deprecation
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated=\
{0} in {1} has been deprecated
# 0: symbol, 1: symbol
# lint: removal
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated.for.removal=\
{0} in {1} has been deprecated and marked for removal
# 0: symbol
# lint: preview
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.is.preview=\
{0} is a preview API and may be removed in a future release.
@ -1947,7 +1948,7 @@ compiler.err.is.preview=\
# 0: symbol
# lint: preview
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.is.preview.reflective=\
{0} is a reflective preview API and may be removed in a future release.
@ -1959,13 +1960,13 @@ compiler.warn.restricted.method=\
# 0: symbol
# lint: deprecation
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated.module=\
module {0} has been deprecated
# 0: symbol
# lint: removal
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated.for.removal.module=\
module {0} has been deprecated and marked for removal
@ -2194,11 +2195,13 @@ compiler.warn.static.not.qualified.by.type2=\
# 0: string, 1: fragment
# lint: options
# flags: default-enabled
compiler.warn.source.no.bootclasspath=\
bootstrap class path is not set in conjunction with -source {0}\n{1}
# 0: string, 1: fragment
# lint: options
# flags: default-enabled
compiler.warn.source.no.system.modules.path=\
location of system modules is not set in conjunction with -source {0}\n{1}
@ -2224,11 +2227,13 @@ compiler.misc.source.no.system.modules.path.with.target=\
# 0: string
# lint: options
# flags: default-enabled
compiler.warn.option.obsolete.source=\
source value {0} is obsolete and will be removed in a future release
# 0: target
# lint: options
# flags: default-enabled
compiler.warn.option.obsolete.target=\
target value {0} is obsolete and will be removed in a future release
@ -2241,6 +2246,7 @@ compiler.err.option.removed.target=\
Target option {0} is no longer supported. Use {1} or later.
# lint: options
# flags: default-enabled
compiler.warn.option.obsolete.suppression=\
To suppress warnings about obsolete options, use -Xlint:-options.
@ -2365,13 +2371,13 @@ compiler.warn.unchecked.assign=\
# 0: symbol, 1: type
# lint: unchecked
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
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, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.call.mbr.of.raw.type=\
unchecked call to {0} as a member of the raw type {1}
@ -2381,7 +2387,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, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.meth.invocation.applied=\
unchecked method invocation: {0} {1} in {4} {5} is applied to given types\n\
required: {2}\n\
@ -2389,13 +2395,13 @@ compiler.warn.unchecked.meth.invocation.applied=\
# 0: type
# lint: unchecked
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.generic.array.creation=\
unchecked generic array creation for varargs parameter of type {0}
# 0: type
# lint: unchecked
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.varargs.non.reifiable.type=\
Possible heap pollution from parameterized vararg type {0}
@ -2794,7 +2800,7 @@ compiler.misc.prob.found.req=\
# 0: message segment, 1: type, 2: type
# lint: unchecked
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.prob.found.req=\
{0}\n\
required: {2}\n\
@ -3191,14 +3197,14 @@ compiler.err.override.incompatible.ret=\
# 0: message segment, 1: type, 2: type
# lint: unchecked
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
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, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.override.unchecked.thrown=\
{0}\n\
overridden method does not throw {1}
@ -3302,13 +3308,13 @@ compiler.err.preview.feature.disabled.classfile=\
# 0: message segment (feature)
# lint: preview
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
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, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.preview.feature.use.plural=\
{0} are a preview feature and may be removed in a future release.
@ -3879,6 +3885,7 @@ compiler.err.bad.name.for.option=\
# 0: option name, 1: symbol
# lint: options
# flags: default-enabled
compiler.warn.module.for.option.not.found=\
module name in {0} option not found: {1}
@ -3895,6 +3902,7 @@ compiler.err.add.reads.with.release=\
adding read edges for system module {0} is not allowed with --release
# lint: options
# flags: default-enabled
compiler.warn.addopens.ignored=\
--add-opens has no effect at compile time
@ -4272,7 +4280,7 @@ compiler.err.incorrect.number.of.nested.patterns=\
# 0: kind name, 1: symbol
# lint: preview
# flags: aggregate, mandatory
# flags: aggregate, mandatory, default-enabled
compiler.warn.declared.using.preview=\
{0} {1} is declared using a preview feature, which may be removed in a future release.

View File

@ -368,6 +368,36 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
* the end position of the tree node. Otherwise, just returns the
* same as getPreferredPosition(). */
int getEndPosition(EndPosTable endPosTable);
/** Get the position that determines which Lint configuration applies. */
default int getLintPosition() {
return getStartPosition();
}
/** Create a new instance from this instance and the given lint position. */
default DiagnosticPosition withLintPosition(int lintPos) {
DiagnosticPosition orig = this;
return new DiagnosticPosition() {
@Override
public JCTree getTree() {
return orig.getTree();
}
@Override
public int getStartPosition() {
return orig.getStartPosition();
}
@Override
public int getPreferredPosition() {
return orig.getPreferredPosition();
}
@Override
public int getEndPosition(EndPosTable endPosTable) {
return orig.getEndPosition(endPosTable);
}
@Override
public int getLintPosition() {
return lintPos;
}
};
}
}
/**
@ -405,6 +435,10 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
RECOVERABLE,
NON_DEFERRABLE,
COMPRESSED,
/** Flag for lint diagnostics that should be emitted even when their category
* is not explicitly enabled, as long as it is not explicitly suppressed.
*/
DEFAULT_ENABLED,
/** Flags mandatory warnings that should pass through a mandatory warning aggregator.
*/
AGGREGATE,

View File

@ -32,29 +32,45 @@ import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.api.DiagnosticFormatter;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
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.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeScanner;
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 com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import static com.sun.tools.javac.main.Option.*;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
import static com.sun.tools.javac.code.Lint.LintCategory.*;
import static com.sun.tools.javac.resources.CompilerProperties.LintWarnings.RequiresAutomatic;
import static com.sun.tools.javac.resources.CompilerProperties.LintWarnings.RequiresTransitiveAutomatic;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
/** A class for error logs. Reports errors and warnings, and
* keeps track of error numbers and positions.
@ -103,6 +119,11 @@ public class Log extends AbstractLog {
*/
protected final DiagnosticHandler prev;
/**
* Diagnostics waiting for an applicable {@link Lint} instance.
*/
protected Map<JavaFileObject, List<JCDiagnostic>> lintWaitersMap = new LinkedHashMap<>();
/**
* Install this diagnostic handler as the current one,
* recording the previous one.
@ -113,9 +134,92 @@ public class Log extends AbstractLog {
}
/**
* Handle a diagnostic.
* Step 1: Handle a diagnostic for which the applicable Lint instance (if any) may not be known yet.
*/
public abstract void report(JCDiagnostic diag);
public final void report(JCDiagnostic diag) {
Lint lint = null;
LintCategory category = diag.getLintCategory();
if (category != null) { // this is a lint warning; find the applicable Lint
DiagnosticPosition pos = diag.getDiagnosticPosition();
if (pos != null && category.annotationSuppression) { // we should apply the Lint from the warning's position
if ((lint = lintFor(diag)) == null) {
addLintWaiter(currentSourceFile(), diag); // ...but we don't know it yet, so defer
return;
}
} else // we should apply the root Lint
lint = rootLint();
}
reportWithLint(diag, lint);
}
/**
* Step 2: Handle a diagnostic for which the applicable Lint instance (if any) is known and provided.
*/
public final void reportWithLint(JCDiagnostic diag, Lint lint) {
// Apply hackery for REQUIRES_TRANSITIVE_AUTOMATIC (see also Check.checkModuleRequires())
if (diag.getCode().equals(RequiresTransitiveAutomatic.key()) && !lint.isEnabled(REQUIRES_TRANSITIVE_AUTOMATIC)) {
reportWithLint(
diags.warning(null, diag.getDiagnosticSource(), diag.getDiagnosticPosition(), RequiresAutomatic), lint);
return;
}
// Apply the lint configuration (if any) and discard the warning if it gets filtered out
if (lint != null) {
LintCategory category = diag.getLintCategory();
boolean emit = !diag.isFlagSet(DEFAULT_ENABLED) ? // is the warning not enabled by default?
lint.isEnabled(category) : // then emit if the category is enabled
category.annotationSuppression ? // else emit if the category is not suppressed, where
!lint.isSuppressed(category) : // ...suppression happens via @SuppressWarnings
!options.isLintDisabled(category); // ...suppression happens via -Xlint:-category
if (!emit)
return;
}
// Proceed
reportReady(diag);
}
/**
* Step 3: Handle a diagnostic to which the applicable Lint instance (if any) has been applied.
*/
protected abstract void reportReady(JCDiagnostic diag);
protected void addLintWaiter(JavaFileObject sourceFile, JCDiagnostic diagnostic) {
lintWaitersMap.computeIfAbsent(sourceFile, s -> new LinkedList<>()).add(diagnostic);
}
/**
* Flush any lint waiters whose {@link Lint} configurations are now known.
*/
public void flushLintWaiters() {
lintWaitersMap.entrySet().removeIf(entry -> {
// Is the source file no longer recognized? If so, discard warnings (e.g., this can happen with JShell)
JavaFileObject sourceFile = entry.getKey();
if (!lintMapper.isKnown(sourceFile))
return true;
// Flush those diagnostics for which we now know the applicable Lint
List<JCDiagnostic> diagnosticList = entry.getValue();
JavaFileObject prevSourceFile = useSource(sourceFile);
try {
diagnosticList.removeIf(diag -> {
Lint lint = lintFor(diag);
if (lint != null) {
reportWithLint(diag, lint);
return true;
}
return false;
});
} finally {
useSource(prevSourceFile);
}
// Discard list if empty
return diagnosticList.isEmpty();
});
}
}
/**
@ -124,7 +228,10 @@ public class Log extends AbstractLog {
public class DiscardDiagnosticHandler extends DiagnosticHandler {
@Override
public void report(JCDiagnostic diag) { }
protected void addLintWaiter(JavaFileObject sourceFile, JCDiagnostic diagnostic) { }
@Override
protected void reportReady(JCDiagnostic diag) { }
}
/**
@ -157,11 +264,20 @@ public class Log extends AbstractLog {
}
@Override
public void report(JCDiagnostic diag) {
protected void reportReady(JCDiagnostic diag) {
if (deferrable(diag)) {
deferred.add(diag);
} else {
prev.report(diag);
prev.reportReady(diag);
}
}
@Override
protected void addLintWaiter(JavaFileObject sourceFile, JCDiagnostic diag) {
if (deferrable(diag)) {
super.addLintWaiter(sourceFile, diag);
} else {
prev.addLintWaiter(sourceFile, diag);
}
}
@ -182,6 +298,13 @@ public class Log extends AbstractLog {
.filter(accepter)
.forEach(prev::report);
deferred = null; // prevent accidental ongoing use
// Flush matching Lint waiters to the previous handler
lintWaitersMap.forEach(
(sourceFile, diagnostics) -> diagnostics.stream()
.filter(accepter)
.forEach(diagnostic -> prev.addLintWaiter(sourceFile, diagnostic)));
lintWaitersMap = null; // prevent accidental ongoing use
}
/** Report all deferred diagnostics in the specified order. */
@ -247,6 +370,16 @@ public class Log extends AbstractLog {
*/
private final Context context;
/**
* The {@link Options} singleton.
*/
private final Options options;
/**
* The lint positions table.
*/
private final LintMapper lintMapper;
/**
* The root {@link Lint} singleton.
*/
@ -350,6 +483,8 @@ public class Log extends AbstractLog {
super(JCDiagnostic.Factory.instance(context));
context.put(logKey, this);
this.context = context;
this.options = Options.instance(context);
this.lintMapper = LintMapper.instance(context);
this.writers = writers;
@SuppressWarnings("unchecked") // FIXME
@ -369,7 +504,6 @@ public class Log extends AbstractLog {
this.diagFormatter = new BasicDiagnosticFormatter(messages);
// Once Options is ready, complete the initialization
final Options options = Options.instance(context);
options.whenReady(this::initOptions);
}
// where
@ -689,6 +823,21 @@ public class Log extends AbstractLog {
diagnosticHandler.report(diagnostic);
}
// Deferred Lint Calculation
/**
* Report unreported lint warnings for which the applicable {@link Lint} configuration is now known.
*/
public void reportOutstandingWarnings() {
diagnosticHandler.flushLintWaiters();
}
// Get the Lint config for the given warning (if known)
private Lint lintFor(JCDiagnostic diag) {
Assert.check(diag.getLintCategory() != null);
return lintMapper.lintAt(diag.getSource(), diag.getDiagnosticPosition()).orElse(null);
}
// Obtain root Lint singleton lazily to avoid init loops
private Lint rootLint() {
if (rootLint == null)
@ -756,7 +905,7 @@ public class Log extends AbstractLog {
private class DefaultDiagnosticHandler extends DiagnosticHandler {
@Override
public void report(JCDiagnostic diagnostic) {
protected void reportReady(JCDiagnostic diagnostic) {
if (expectDiagKeys != null)
expectDiagKeys.remove(diagnostic.getCode());
@ -783,13 +932,13 @@ public class Log extends AbstractLog {
// Apply the appropriate mandatory warning aggregator, if needed
if (diagnostic.isFlagSet(AGGREGATE)) {
LintCategory category = diagnostic.getLintCategory();
boolean verbose = rootLint().isEnabled(category);
boolean verbose = lintFor(diagnostic).isEnabled(category);
if (!aggregatorFor(category).aggregate(diagnostic, verbose))
return;
}
// Strict warnings are always emitted
if (diagnostic.isFlagSet(DiagnosticFlag.STRICT)) {
if (diagnostic.isFlagSet(STRICT)) {
writeDiagnostic(diagnostic);
nwarnings++;
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -41,7 +41,7 @@ import javax.tools.SimpleJavaFileObject;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
@ -130,10 +130,11 @@ public class TestLog
log.error(tree.pos(), Errors.NotStmt);
log.error(nil, Errors.NotStmt);
log.warning(LintWarnings.DivZero);
log.warning(tree.pos, LintWarnings.DivZero);
log.warning(tree.pos(), LintWarnings.DivZero);
log.warning(nil, LintWarnings.DivZero);
// some warnings that will be emitted during parsing
log.warning(Warnings.ExtraneousSemicolon);
log.warning(tree.pos, Warnings.ExtraneousSemicolon);
log.warning(tree.pos(), Warnings.ExtraneousSemicolon);
log.warning(nil, Warnings.ExtraneousSemicolon);
}
private Log log;

View File

@ -730,8 +730,8 @@ public class ImportModule extends TestRunner {
.getOutputLines(Task.OutputKind.DIRECT);
List<String> expectedErrors = List.of(
"module-info.java:3:18: compiler.warn.module.not.found: M1",
"module-info.java:6:9: compiler.err.cant.resolve: kindname.class, A, , ",
"module-info.java:3:18: compiler.warn.module.not.found: M1",
"1 error",
"1 warning"
);

View File

@ -1,4 +1,4 @@
T6400189a.java:14:35: compiler.warn.unchecked.call.mbr.of.raw.type: <T>getAnnotation(java.lang.Class<T>), java.lang.reflect.Constructor
T6400189a.java:14:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.annotation.Annotation, java.lang.annotation.Documented)
T6400189a.java:14:35: compiler.warn.unchecked.call.mbr.of.raw.type: <T>getAnnotation(java.lang.Class<T>), java.lang.reflect.Constructor
1 error
1 warning

View File

@ -1,4 +1,4 @@
T6400189b.java:24:24: compiler.warn.unchecked.call.mbr.of.raw.type: <T>m(T6400189b<T>), T6400189b.B
T6400189b.java:24:24: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer)
T6400189b.java:24:24: compiler.warn.unchecked.call.mbr.of.raw.type: <T>m(T6400189b<T>), T6400189b.B
1 error
1 warning

View File

@ -1,7 +1,7 @@
DanglingDocCommentsClass.java:15:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:19:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:10:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:13:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:14:8: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:14:69: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:15:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:19:5: compiler.warn.dangling.doc.comment
6 warnings

View File

@ -1,7 +1,7 @@
DanglingDocCommentsClass_Line.java:21:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:26:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:11:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:15:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:17:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:19:9: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:21:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:26:5: compiler.warn.dangling.doc.comment
6 warnings

View File

@ -1,4 +1,4 @@
DanglingDocCommentsClass_Mixed.java:13:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Mixed.java:17:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Mixed.java:21:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Mixed.java:13:1: compiler.warn.dangling.doc.comment
3 warnings

View File

@ -1,8 +1,8 @@
DanglingDocCommentsEnum.java:16:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:22:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:28:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:10:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:13:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:14:8: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:14:67: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:16:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:22:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:28:5: compiler.warn.dangling.doc.comment
7 warnings

View File

@ -1,11 +1,11 @@
T7188968.java:20:20: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:20:9: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List<X>,java.lang.Object), T7188968.Foo
T7188968.java:21:20: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:21:29: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List<X>,java.lang.Object), T7188968.Foo
T7188968.java:22:22: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:23:24: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:20:9: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List<X>,java.lang.Object), T7188968.Foo
T7188968.java:21:29: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List<X>,java.lang.Object), T7188968.Foo
T7188968.java:22:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.util.List<X>,java.lang.Object, java.util.List,unknown, kindname.class, T7188968.Foo
T7188968.java:22:19: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List<X>
T7188968.java:23:24: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:23:20: compiler.warn.unchecked.meth.invocation.applied: kindname.method, makeFoo, java.util.List<Z>,java.lang.Object, java.util.List,unknown, kindname.class, T7188968.Foo
T7188968.java:23:21: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List<Z>
4 errors

View File

@ -1,4 +1,4 @@
TargetType22.java:29:21: compiler.warn.unchecked.varargs.non.reifiable.type: A
TargetType22.java:40:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType22.Sam1<java.lang.String>), TargetType22, kindname.method, call(TargetType22.SamX<java.lang.String>), TargetType22
TargetType22.java:29:21: compiler.warn.unchecked.varargs.non.reifiable.type: A
1 error
1 warning

View File

@ -0,0 +1,170 @@
/*
* @test /nodynamiccopyright/
* @bug 8224228
* @summary Verify lexical lint warnings handle nested declarations with SuppressWarnings correctly
* @compile/fail/ref=LexicalLintNesting.out -XDrawDiagnostics -Xlint:text-blocks -Werror LexicalLintNesting.java
*/
//@SuppressWarnings("text-blocks")
public class LexicalLintNesting {
//@SuppressWarnings("text-blocks")
/* WARNING HERE */ String s1 = """
trailing space here:\u0020
""";
@SuppressWarnings("text-blocks")
String s2 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
public static class Nested1 {
@SuppressWarnings("text-blocks")
String s3 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
/* WARNING HERE */ String s4 = """
trailing space here:\u0020
""";
@SuppressWarnings("text-blocks")
public static class Nested1A {
//@SuppressWarnings("text-blocks")
String s5 = """
trailing space here:\u0020
""";
@SuppressWarnings("text-blocks")
String s6 = """
trailing space here:\u0020
""";
}
@SuppressWarnings("text-blocks")
String s7 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
/* WARNING HERE */ String s8 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
public static class Nested1B {
@SuppressWarnings("text-blocks")
String s9 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
/* WARNING HERE */ String s10 = """
trailing space here:\u0020
""";
}
@SuppressWarnings("text-blocks")
String s11 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
/* WARNING HERE */ String s12 = """
trailing space here:\u0020
""";
}
@SuppressWarnings("text-blocks")
String s13 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
/* WARNING HERE */ String s14 = """
trailing space here:\u0020
""";
@SuppressWarnings("text-blocks")
public static class Nested2 {
@SuppressWarnings("text-blocks")
String s15 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
String s16 = """
trailing space here:\u0020
""";
@SuppressWarnings("text-blocks")
public static class Nested2A {
//@SuppressWarnings("text-blocks")
String s17 = """
trailing space here:\u0020
""";
@SuppressWarnings("text-blocks")
String s18 = """
trailing space here:\u0020
"""; // SHOULD NOT get a warning here
}
@SuppressWarnings("text-blocks")
String s19 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
String s20 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
public static class Nested2B {
@SuppressWarnings("text-blocks")
String s21 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
String s22 = """
trailing space here:\u0020
""";
}
@SuppressWarnings("text-blocks")
String s23 = """
trailing space here:\u0020
""";
//@SuppressWarnings("text-blocks")
String s24 = """
trailing space here:\u0020
""";
}
//@SuppressWarnings("text-blocks")
/* WARNING HERE */ String s25 = """
trailing space here:\u0020
""";
@SuppressWarnings("text-blocks")
String s26 = """
trailing space here:\u0020
""";
}

View File

@ -0,0 +1,10 @@
LexicalLintNesting.java:12:36: compiler.warn.trailing.white.space.will.be.removed
LexicalLintNesting.java:30:40: compiler.warn.trailing.white.space.will.be.removed
LexicalLintNesting.java:55:40: compiler.warn.trailing.white.space.will.be.removed
LexicalLintNesting.java:68:45: compiler.warn.trailing.white.space.will.be.removed
LexicalLintNesting.java:80:41: compiler.warn.trailing.white.space.will.be.removed
LexicalLintNesting.java:92:37: compiler.warn.trailing.white.space.will.be.removed
LexicalLintNesting.java:162:37: compiler.warn.trailing.white.space.will.be.removed
- compiler.err.warnings.and.werror
1 error
7 warnings

View File

@ -0,0 +1,61 @@
/*
* @test /nodynamiccopyright/
* @bug 8224228
* @summary Verify SuppressWarnings works for LintCategore.TEXT_BLOCKS
* @compile/fail/ref=TextBlockSuppress.out -XDrawDiagnostics -Xlint:text-blocks -Werror TextBlockSuppress.java
*/
public class TextBlockSuppress {
public static class Example1 {
public void method() {
String s = """
trailing space here:\u0020
"""; // SHOULD get a warning here
}
}
@SuppressWarnings("text-blocks")
public static class Example2 {
public void method() {
String s = """
trailing space here:\u0020
"""; // SHOULD NOT get a warning here
}
}
public static class Example3 {
@SuppressWarnings("text-blocks")
public void method() {
String s = """
trailing space here:\u0020
"""; // SHOULD NOT get a warning here
}
}
public static class Example4 {
{
String s = """
trailing space here:\u0020
"""; // SHOULD get a warning here
}
}
@SuppressWarnings("text-blocks")
public static class Example5 {
{
String s = """
trailing space here:\u0020
"""; // SHOULD NOT get a warning here
}
}
public static class Example6 {
public void method() {
@SuppressWarnings("text-blocks")
String s = """
trailing space here:\u0020
"""; // SHOULD NOT get a warning here
}
}
}

View File

@ -0,0 +1,5 @@
TextBlockSuppress.java:12:24: compiler.warn.trailing.white.space.will.be.removed
TextBlockSuppress.java:38:24: compiler.warn.trailing.white.space.will.be.removed
- compiler.err.warnings.and.werror
1 error
2 warnings

View File

@ -1,4 +1,4 @@
Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
P.java:10:18: compiler.warn.has.been.deprecated: foo(), Q
Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
Q.java:17:25: compiler.warn.has.been.deprecated: foo(), Q
3 warnings

View File

@ -1,4 +1,4 @@
Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
P.java:10:18: compiler.warn.has.been.deprecated: foo(), Q
Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
- compiler.note.deprecated.filename.additional: Q.java
2 warnings

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -599,8 +599,8 @@ public class AnnotationsOnModules extends ModuleTestBase {
"1 warning");
} else if (suppress.equals(DEPRECATED_JAVADOC)) {
expected = Arrays.asList(
"module-info.java:1:19: compiler.warn.missing.deprecated.annotation",
"module-info.java:2:14: compiler.warn.has.been.deprecated.module: m1x",
"module-info.java:1:19: compiler.warn.missing.deprecated.annotation",
"2 warnings");
} else {
expected = Arrays.asList("");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 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
@ -324,7 +324,9 @@ public class PreviewErrors extends ComboInstance<PreviewErrors> {
ok = true;
switch (elementType) {
case LANGUAGE -> {
if (lint == Lint.ENABLE_PREVIEW) {
if (suppress == Suppress.YES) {
expected = Set.of();
} else if (lint == Lint.ENABLE_PREVIEW) {
expected = Set.of("5:41:compiler.warn.preview.feature.use");
} else {
expected = Set.of("-1:-1:compiler.note.preview.filename",

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 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
@ -587,12 +587,12 @@ public class PreviewTest extends TestRunner {
"Test.java:19:11: compiler.err.is.preview: test()",
"Test.java:20:11: compiler.err.is.preview: test()",
"Test.java:21:11: compiler.err.is.preview: test()",
"Test.java:24:11: compiler.warn.is.preview.reflective: test()",
"Test.java:29:16: compiler.err.is.preview: preview.api.Preview",
"Test.java:32:21: compiler.err.is.preview: test()",
"Test.java:36:21: compiler.err.is.preview: test()",
"Test.java:40:13: compiler.err.is.preview: test()",
"Test.java:41:21: compiler.err.is.preview: FIELD",
"Test.java:24:11: compiler.warn.is.preview.reflective: test()",
"17 errors",
"1 warning");
@ -792,6 +792,99 @@ public class PreviewTest extends TestRunner {
throw new Exception("expected output not found" + log);
}
@Test //JDK-8224228:
public void testSuppressWarnings(Path base) throws Exception {
Path apiSrc = base.resolve("api-src");
tb.writeJavaFiles(apiSrc,
"""
package preview.api;
@jdk.internal.javac.PreviewFeature(feature=jdk.internal.javac.PreviewFeature.Feature.TEST)
public class Preview {
public static int test() {
return 0;
}
}
""");
Path apiClasses = base.resolve("api-classes");
new JavacTask(tb, Task.Mode.CMDLINE)
.outdir(apiClasses)
.options("--patch-module", "java.base=" + apiSrc.toString(),
"-Werror")
.files(tb.findJavaFiles(apiSrc))
.run()
.writeAll()
.getOutputLines(Task.OutputKind.DIRECT);
Path testSrc = base.resolve("test-src");
tb.writeJavaFiles(testSrc,
"""
package test;
import preview.api.Preview;
public class Test {
public static class Example1 {
public void method() {
Preview.test(); // SHOULD get a warning here
}
}
@SuppressWarnings("preview")
public static class Example2 {
public void method() {
Preview.test(); // SHOULD NOT get a warning here
}
}
public static class Example3 {
@SuppressWarnings("preview")
public void method() {
Preview.test(); // SHOULD NOT get a warning here
}
}
public static class Example4 {
{
Preview.test(); // SHOULD get a warning here
}
}
@SuppressWarnings("preview")
public static class Example5 {
{
Preview.test(); // SHOULD NOT get a warning here
}
}
public static class Example6 {
@SuppressWarnings("preview")
int x = Preview.test(); // SHOULD NOT get a warning here
}
}
""");
Path testClasses = base.resolve("test-classes");
List<String> log = new JavacTask(tb, Task.Mode.CMDLINE)
.outdir(testClasses)
.options("--patch-module", "java.base=" + apiClasses.toString(),
"--add-exports", "java.base/preview.api=ALL-UNNAMED",
"--enable-preview",
"-Xlint:preview",
"-source", String.valueOf(Runtime.version().feature()),
"-XDrawDiagnostics")
.files(tb.findJavaFiles(testSrc))
.run(Task.Expect.SUCCESS)
.writeAll()
.getOutputLines(Task.OutputKind.DIRECT);
List<String> expected =
List.of("Test.java:7:11: compiler.warn.is.preview: preview.api.Preview",
"Test.java:27:11: compiler.warn.is.preview: preview.api.Preview",
"2 warnings");
if (!log.equals(expected))
throw new Exception("expected output not found: " + log);
}
@Test //JDK-8343540:
public void nonPreviewImplementsPreview5(Path base) throws Exception {
Path apiSrc = base.resolve("api-src");

View File

@ -1,6 +1,6 @@
T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls
T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls
T7097436.java:15:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List<java.lang.String>[], java.lang.String)
T7097436.java:16:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List<java.lang.String>[], java.lang.Integer[])
T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls
T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls
2 errors
2 warnings

View File

@ -1,7 +1,7 @@
T6594914a.java:11:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:16:16: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:16:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:17:20: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:24:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
6 warnings

View File

@ -1,14 +1,14 @@
T7090499.java:26:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:27:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:28:17: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:28:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:18:5: compiler.warn.raw.class.use: T7090499, T7090499<E>
T7090499.java:18:22: compiler.warn.raw.class.use: T7090499, T7090499<E>
T7090499.java:20:10: compiler.warn.raw.class.use: T7090499.A.X, T7090499<E>.A<X>.X
T7090499.java:21:10: compiler.warn.raw.class.use: T7090499.A.Z, T7090499<E>.A<X>.Z<Y>
T7090499.java:24:17: compiler.warn.raw.class.use: T7090499.B, T7090499.B<X>
T7090499.java:26:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:27:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:28:18: compiler.warn.raw.class.use: T7090499.B, T7090499.B<X>
T7090499.java:28:17: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:28:11: compiler.warn.raw.class.use: T7090499.B, T7090499.B<X>
T7090499.java:28:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:30:32: compiler.warn.raw.class.use: T7090499.B, T7090499.B<X>
T7090499.java:33:13: compiler.warn.raw.class.use: T7090499.A, T7090499<E>.A<X>
T7090499.java:33:24: compiler.warn.raw.class.use: T7090499.A, T7090499<E>.A<X>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
@ -116,8 +116,8 @@ public class UnneededStrictfpWarningToolBox extends TestRunner {
var expected = List.of("UnneededStrictfpWarning1.java:1:17: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:10:10: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:12:29: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:16:28: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:18:21: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:16:28: compiler.warn.strictfp",
"5 warnings");
checkLog(log, expected);
}

View File

@ -1,19 +1,19 @@
T6480588.java:16:24: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:16:51: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
T6480588.java:15:2: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:18:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:18:12: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:18:65: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:30:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:33:25: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:33:52: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
T6480588.java:32:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:17:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:18:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:29:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:19:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:19:34: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:21:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:21:25: compiler.warn.deprecated.annotation.has.no.effect: kindname.variable
T6480588.java:21:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:30:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:29:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:30:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:33:25: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:33:52: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
T6480588.java:32:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
18 warnings