RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v7]
Maurizio Cimadamore
mcimadamore at openjdk.org
Wed Jul 30 17:13:03 UTC 2025
On Wed, 30 Jul 2025 15:54:45 GMT, Archie Cobbs <acobbs at openjdk.org> wrote:
>> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied.
>>
>> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation.
>>
>> In addition, several other factors complicate things:
>> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any
>> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_)
>> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning)
>> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled
>> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings
>> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags
>> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed.
>>
>> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode".
>>
>> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above.
>
> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision:
>
> More simplification of LintMapper per review suggestions.
src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 299:
> 297: * The tree is sparse: only declarations that differ from their parent are included.
> 298: */
> 299: private static class MappedDeclBuilder extends TreeScanner {
Another (maybe picky) comment: to my eyes, `MappedDeclBuilder` is really a mutable data structure. It has operations to find nodes, but it doesn't provide operation to _add_ new nodes. Instead the _add_ operation is delegated to this builder class.
Now, I totally understand that the process of adding a new entry to `MappedDecl` is complex, and you need to scan a tree to get there. That's all good. But I think you do want an `add(Span, JCTree)` to `MappedDecl` which can then be used inside `FileInfo::afterAttr`. The fact that the implementation of this `add` method is defined in terms of a tree scanner is an impl detail that doesn't need to be known outside the `add` method (and you can in fact turn the scanner into a local class, and then have the visitor create a new scanner, and process the provided tree with it. This should encapsulate the data structure modelled by `MappedDecl` even more.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2243364077
More information about the kulla-dev
mailing list