Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8224228: No way to locally suppress lint warnings in parser/tokenizer or preview features #23237

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8557999
Some cleanups relating to MandatoryWarningHandler.
archiecobbs Jan 16, 2025
224bd43
Refactor DeferredLintHandler to handle warnings generated during pars…
archiecobbs Jan 19, 2025
e4ef8f0
Merge branch 'master' into JDK-8224228
archiecobbs Jan 19, 2025
d1d16d8
Bug fixes.
archiecobbs Jan 21, 2025
3a0ac64
Merge branch 'master' into JDK-8224228
archiecobbs Jan 22, 2025
2509771
Fixes and cleanups.
archiecobbs Jan 22, 2025
9f1c259
Update DeferredLintHandler API to use JCTree instead of DiagnosticPos…
archiecobbs Jan 23, 2025
893fef8
Add Javadoc to document a subtley in the API.
archiecobbs Jan 23, 2025
405f3a4
Refactor the DeferredLintHandler API to maintain the "stack" itself.
archiecobbs Jan 23, 2025
7adada7
Merge branch 'JDK-8348427' into JDK-8224228
archiecobbs Jan 23, 2025
877b16c
Remove Attr.flushDeferredLintHandler() which doesn't appear necessary.
archiecobbs Jan 23, 2025
cecb228
Put back required flushing of binding pattern variable declaration.
archiecobbs Jan 23, 2025
0ce44d6
Merge branch 'master' into JDK-8347958 to fix conflict.
archiecobbs Jan 25, 2025
03f08d9
Merge branch 'master' into JDK-8224228 to fix conflict.
archiecobbs Jan 26, 2025
6cc1eae
Merge branch 'JDK-8347958' into JDK-8224228
archiecobbs Jan 26, 2025
7ad56bb
Instead of using EndPosTable, track ending positions of declarations …
archiecobbs Jan 28, 2025
40872df
Refactor to eliminate the unnecessary MandatoryWarningHandler "verbos…
archiecobbs Jan 29, 2025
73a5e88
Fix bugs when mapping lexical deferrals to declarations.
archiecobbs Jan 29, 2025
ebb6544
Refactor "dangling-doc-comments" logic to utilize new DeferredLintHan…
archiecobbs Jan 29, 2025
11b43d4
Fix an inaccurate comment.
archiecobbs Jan 30, 2025
35f99ff
Refactor to remove the "log" parameter from Lint.logIfEnabled().
archiecobbs Jan 31, 2025
376c418
Merge branch 'JDK-8349155' into JDK-8224228
archiecobbs Jan 31, 2025
44f5bed
Revert gratuituous whitespace change.
archiecobbs Jan 31, 2025
e83c88c
Merge branch 'master' into JDK-8224228
archiecobbs Feb 6, 2025
615d014
Merge branch 'master' into JDK-8224228 to fix conflicts.
archiecobbs Feb 12, 2025
6557782
Update copyright dates.
archiecobbs Feb 12, 2025
4fcc612
Track source end positions of declarations that support @SuppressWarn…
archiecobbs Feb 18, 2025
e235228
Add end position for variables coming from variableDeclaratorId().
archiecobbs Feb 18, 2025
fcccaa3
Merge branch 'JDK-8350212' (end positions sub-task) into JDK-8224228.
archiecobbs Feb 18, 2025
8ac827c
Remove unneeded end position tracking.
archiecobbs Feb 18, 2025
de6f80c
Refactor MandatoryWarningHandler to support dynamic verbosity.
archiecobbs Feb 21, 2025
f1e2a59
Merge branch 'JDK-8350514' (split out as sub-task) into JDK-8224228.
archiecobbs Feb 21, 2025
1161e80
Refactor to map positions to declarations all within the parser.
archiecobbs Feb 28, 2025
45c2aac
Add node type assertion check to endDecl() per review suggestion.
archiecobbs Feb 28, 2025
12d8c73
Rejigger LexicalLintHandler so it runs in linear time; add unit test.
archiecobbs Feb 28, 2025
31ef44b
Fix inconsistent bracket styling.
archiecobbs Feb 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -25,9 +25,10 @@

package com.sun.tools.javac.parser;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicReference;

import com.sun.tools.javac.code.DeferredLintHandler;
import com.sun.tools.javac.code.DeferredLintHandler.LintLogger;
@@ -37,7 +38,6 @@
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;

/**
* Stashes lint warnings suppressible via {@code @SuppressWarnings} and their source code
@@ -51,10 +51,8 @@
public class LexicalLintHandler {

private final LinkedList<Report> reports = new LinkedList<>();
private final ArrayDeque<DeclNode> declNodes = new ArrayDeque<>();
private final ArrayList<DeclNode> declNodes = new ArrayList<>();

private int lastFlushedStartPos;
private int lastFlushedEndPos;
private boolean flushed;

// Public API
@@ -87,13 +85,29 @@ public void report(DiagnosticPosition pos, LintWarning key) {
* @return the given {@code decl} (for fluent chaining)
*/
public <T extends JCTree> T endDecl(T decl, int endPos) {

// Basic sanity checks
Assert.check(!flushed);
Assert.check(decl.getTag() == Tag.MODULEDEF
|| decl.getTag() == Tag.PACKAGEDEF
|| decl.getTag() == Tag.CLASSDEF
|| decl.getTag() == Tag.METHODDEF
|| decl.getTag() == Tag.VARDEF);
declNodes.addLast(new DeclNode(decl, endPos));

// Create new declaration node
DeclNode declNode = new DeclNode(decl, endPos);

// Verify our assumptions about declarations:
// 1. If two declarations overlap, then one of them must nest within the other
// 2. endDecl() is invoked in order of increasing declaration ending position
if (!declNodes.isEmpty()) {
DeclNode prevNode = declNodes.get(declNodes.size() - 1);
Assert.check(declNode.endPos() >= prevNode.endPos());
Assert.check(declNode.startPos() >= prevNode.endPos() || declNode.startPos() <= prevNode.startPos());
}

// Add node to the list
declNodes.add(declNode);
return decl;
}

@@ -109,13 +123,33 @@ public void flushTo(DeferredLintHandler deferredLintHandler) {
Assert.check(!flushed);
flushed = true;

// Flush reports contained within any of the declaration nodes we have gathered
declNodes.forEach(declNode -> flushDeclReports(deferredLintHandler, declNode));
declNodes.clear();
// Assign the innermost containing declaration, if any, to each report
ListIterator<Report> reportIterator = reports.listIterator(0);
declLoop:
for (DeclNode declNode : declNodes) {
while (true) {
if (!reportIterator.hasNext())
break declLoop;
Report report = reportIterator.next();
switch (report.relativeTo(declNode)) {
case BEFORE: // report is contained by some outer declaration, or is "top level"
continue;
case WITHIN: // assign to this declaration, unless contained by an inner declaration
report.decl().compareAndSet(null, declNode.decl());
continue;
case AFTER: // we've gone too far, backup one step and go to the next declaration
reportIterator.previous();
continue declLoop;
}
}
}

// Flush the remaining reports, which must be "top level" (i.e., not contained within any declaration)
reports.forEach(report -> flushReport(deferredLintHandler, report));
// Now flush all the reports
reports.forEach(report -> report.flushTo(deferredLintHandler));

// Clean up
reports.clear();
declNodes.clear();
}

// Internal Methods
@@ -134,73 +168,45 @@ private void addReport(Report report) {
i.add(report);
}

// Flush all reports contained within the given declaration
private void flushDeclReports(DeferredLintHandler deferredLintHandler, DeclNode declNode) {

// Get declaration's starting position so we know its lexical range
int startPos = TreeInfo.getStartPos(declNode.decl());
int endPos = declNode.endPos();

// Sanity check our assumptions about declarations:
// 1. If two declarations overlap, then one of them must nest within the other
// 2. endDecl() is always invoked in order of increasing declaration ending position
Assert.check(endPos >= lastFlushedEndPos);
Assert.check(startPos >= lastFlushedEndPos || startPos <= lastFlushedStartPos);
// DeclNode

// Find all reports contained by the declaration; they should all be at or near the end of the list
ListIterator<Report> i = reports.listIterator(reports.size());
int count = 0;
while (i.hasPrevious()) {
switch (i.previous().compareToRange(startPos, endPos)) {
case AFTER: // unusual; e.g., report is contained in the next token after declaration
continue;
case WITHIN: // report is contained in the declaration, so we will flush it
count++;
continue;
case BEFORE: // we've gone too far, backup one step and start here
i.next();
break;
}
break;
}
// A declaration that has been created and whose starting and ending positions are known
private record DeclNode(JCTree decl, int startPos, int endPos) {

// Flush the reports contained by the declaration (in order). Note, we know that it is the innermost
// containing declaration because any more deeply nested declarations must have already been flushed
// by now; this follows from the above assumptions.
deferredLintHandler.push(declNode.decl());
try {
while (count-- > 0) {
flushReport(deferredLintHandler, i.next());
i.remove();
}
} finally {
deferredLintHandler.pop();
DeclNode(JCTree decl, int endPos) {
this(decl, TreeInfo.getStartPos(decl), endPos);
}

// Update markers
lastFlushedStartPos = startPos;
lastFlushedEndPos = endPos;
}

private void flushReport(DeferredLintHandler deferredLintHandler, Report report) {
deferredLintHandler.report(report.logger());
}

// DeclNode

// A declaration that has been created and whose starting and ending positions are known
private record DeclNode(JCTree decl, int endPos) { }

// Report

// A warning report that has not yet been flushed to the DeferredLintHandler
private record Report(int pos, LintLogger logger) {
private record Report(int pos, LintLogger logger, AtomicReference<JCTree> decl) {

Report(int pos, LintLogger logger) {
this(pos, logger, new AtomicReference<>());
}

// Flush this report to the DeferredLintHandler using our assigned declaration (if any)
void flushTo(DeferredLintHandler deferredLintHandler) {
JCTree decl = decl().get();
if (decl != null)
deferredLintHandler.push(decl);
try {
deferredLintHandler.report(logger());
} finally {
if (decl != null)
deferredLintHandler.pop();
}
}

// Compare our position to the given range
Direction compareToRange(int minPos, int maxPos) {
if (pos() < minPos)
// Determine our position relative to the range spanned by the given declaration
Direction relativeTo(DeclNode declNode) {
int startPos = declNode.startPos();
int endPos = declNode.endPos();
if (pos() < startPos)
return Direction.BEFORE;
if (pos() == minPos || (pos() > minPos && pos() < maxPos)) {
if (pos() == startPos || (pos() > startPos && pos() < endPos)) {
return Direction.WITHIN;
}
return Direction.AFTER;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
@@ -22,6 +22,8 @@
*/

// key: compiler.err.bad.file.name
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: -source ${jdk.version} --enable-preview

public static void main(String... args) {
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
@@ -22,6 +22,8 @@
*/

// key: compiler.err.implicit.class.should.not.have.package.declaration
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: -source ${jdk.version} --enable-preview

package implicit.classes;
170 changes: 170 additions & 0 deletions test/langtools/tools/javac/lint/LexicalLintNesting.java
Original file line number Diff line number Diff line change
@@ -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
""";
}
10 changes: 10 additions & 0 deletions test/langtools/tools/javac/lint/LexicalLintNesting.out
Original file line number Diff line number Diff line change
@@ -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