Skip to content

Conversation

@archiecobbs
Copy link
Contributor

@archiecobbs archiecobbs commented Apr 10, 2025

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.


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed (2 reviews required, with at least 1 Reviewer, 1 Author)

Issues

  • JDK-8348611: Eliminate DeferredLintHandler and emit warnings after attribution (Enhancement - P5)
  • JDK-8224228: No way to locally suppress lint warnings in parser/tokenizer or preview features (Task - P4)
  • JDK-8353758: Missing calls to Log.useSource() in JavacTrees (Bug - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584
$ git checkout pull/24584

Update a local copy of the PR:
$ git checkout pull/24584
$ git pull https://git.openjdk.org/jdk.git pull/24584/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 24584

View PR using the GUI difftool:
$ git pr show -t 24584

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/24584.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Apr 10, 2025

👋 Welcome back acobbs! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Apr 10, 2025

@archiecobbs This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

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

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 107 new commits pushed to the master branch:

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk
Copy link

openjdk bot commented Apr 10, 2025

@archiecobbs this pull request can not be integrated into master due to one or more merge conflicts. To resolve these merge conflicts and update this pull request you can run the following commands in the local repository for your personal fork:

git checkout JDK-8348611
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push

@openjdk
Copy link

openjdk bot commented Apr 10, 2025

⚠️ @archiecobbs This pull request contains merges that bring in commits not present in the target repository. Since this is not a "merge style" pull request, these changes will be squashed when this pull request in integrated. If this is your intention, then please ignore this message. If you want to preserve the commit structure, you must change the title of this pull request to Merge <project>:<branch> where <project> is the name of another project in the OpenJDK organization (for example Merge jdk:master).

@openjdk openjdk bot added the merge-conflict Pull request has merge conflict with target branch label Apr 10, 2025
@archiecobbs
Copy link
Contributor Author

Hi Jan, thanks for taking a look.

nice to see ThisEscapeAnalyzer is short-circuited, we'll see if there are more than needs to be short-circuited, but probably good to do it when there's a need, rather than pro-actively.

Right - and to elaborate on this a bit: We added the new WARN phase a while back as a comfortable home for ThisEscapeAnalyzer and any other future non-trivial warning calculators. Since WARN comes after ATTR, all attribution and Lint calculations are complete, and so you can always ask, "Is Lint category X enabled here... or here... or over there...?" without worry.

the semantics for BaseFileManager/Locations is slightly complex (the Context there may be a different Context than used by the rest of javac, e.g. when created through javax.tools.JavaCompiler.getStandardFileManager). I think the current code is OK with that - the warnings should be reported using the root Lint, but I am not sure if there are any tests for that. I'll see if I can add a test, but it may be done separately.

Ah, I didn't realize that. In any case it should have the same semantics as before, because in both cases (before and after this change), the Lint and the Log singletons derive from the same Context.

Just for information, do you know/recall what's the exact path to get here with JShell?

If you throw an AssertionError in that particular case, you get a failure in ToolEnablePreviewTest.java that looks like this (but I haven't investigated it any further):

test ToolEnablePreviewTest.testCompilerTestFlag(): failure [406ms]
java.lang.AssertionError: unknown source file: WrappedJavaFileObject[jdk.jshell.MemoryFileManager$SourceMemoryJavaFileObject[string:///$NeverUsedName$.java]]
	at jdk.compiler/com.sun.tools.javac.util.Log$DiagnosticHandler.lambda$flushLintWaiters$0(Log.java:201)
	at java.base/java.util.Collection.removeIf(Collection.java:581)
	at jdk.compiler/com.sun.tools.javac.util.Log$DiagnosticHandler.flushLintWaiters(Log.java:196)
	at jdk.compiler/com.sun.tools.javac.util.Log.reportOutstandingWarnings(Log.java:832)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.errorCount(JavaCompiler.java:583)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:177)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.parse(JavacTaskImpl.java:248)
	at jdk.jshell/jdk.jshell.TaskFactory$ParseTask.parse(TaskFactory.java:384)
	at jdk.jshell/jdk.jshell.TaskFactory$ParseTask.<init>(TaskFactory.java:373)
	at jdk.jshell/jdk.jshell.TaskFactory.lambda$parse$0(TaskFactory.java:149)
	at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$1(TaskFactory.java:218)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:194)
	at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:211)
	at jdk.jshell/jdk.jshell.TaskFactory.parse(TaskFactory.java:145)
	at jdk.jshell/jdk.jshell.TaskFactory.parse(TaskFactory.java:245)
	at jdk.jshell/jdk.jshell.CompletenessAnalyzer.lambda$scan$1(CompletenessAnalyzer.java:96)
	at jdk.jshell/jdk.jshell.CompletenessAnalyzer$Parser.disambiguateDeclarationVsExpression(CompletenessAnalyzer.java:769)
	at jdk.jshell/jdk.jshell.CompletenessAnalyzer$Parser.parseUnit(CompletenessAnalyzer.java:669)
	at jdk.jshell/jdk.jshell.CompletenessAnalyzer.scan(CompletenessAnalyzer.java:97)
	at jdk.jshell/jdk.jshell.SourceCodeAnalysisImpl.analyzeCompletion(SourceCodeAnalysisImpl.java:199)
	at jdk.jshell/jdk.internal.jshell.tool.JShellTool.isComplete(JShellTool.java:1356)
	at jdk.jshell/jdk.internal.jshell.tool.JShellTool.getInput(JShellTool.java:1297)
	at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:1246)
	at jdk.jshell/jdk.internal.jshell.tool.JShellTool.start(JShellTool.java:1031)
	at jdk.jshell/jdk.internal.jshell.tool.JShellToolBuilder.run(JShellToolBuilder.java:259)
	at ReplToolTesting.testRawRun(ReplToolTesting.java:319)
	at ReplToolTesting.testRaw(ReplToolTesting.java:302)
	at ReplToolTesting.test(ReplToolTesting.java:254)
	at ReplToolTesting.test(ReplToolTesting.java:241)
	at ReplToolTesting.test(ReplToolTesting.java:233)
	at ReplToolTesting.test(ReplToolTesting.java:224)
	at ToolEnablePreviewTest.testCompilerTestFlag(ToolEnablePreviewTest.java:97)

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<>();
Copy link
Contributor

@vicente-romero-oracle vicente-romero-oracle Aug 13, 2025

Choose a reason for hiding this comment

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

would it makes sense to make this map a WeakHashMap? I'm thinking about cases where we are not using a ReusableContext and thus this map wont be cleared.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

would it makes sense to make this map a WeakHashMap? I'm thinking about cases where we are not using a ReusableContext and thus this map wont be cleared.

Frankly I'm a little fuzzy on that. If there were an issue with LintMapper.fileInfoMap, then wouldn't the same issue exist with AbstractLog.sourceMap? Note LintMapper.clear() and Log.clear() are called at the same time, so it seems in any given scenario, they are going to either both be cleared or both not be cleared.

Copy link
Contributor

@vicente-romero-oracle vicente-romero-oracle Aug 13, 2025

Choose a reason for hiding this comment

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

yes you are right we have other DSs with the same issue if any. I guess discuss and address it as a separate issue

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes you are right we have other DSs with the same issue if any. I guess discuss and address it as a separate issue

I'm not familiar with all of the various compiler life-cycle variants, but I guess it would boil down to the question, "In what scenarios would a Context that's not a ReusableContext be reused for multiple compilations?"

Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, this is an instance field on a Context service - it will be GCed when the given javac instance is GCed. I think in most cases, use of weak maps is not necessary.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was worried about holding unnecessary memory withing one javac instance

private record LintRange(
Span span, // declaration's lexical range
Lint lint, // the Lint configuration that applies at this declaration
Symbol symbol, // declaration symbol (for debug purposes only; null for root)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: should we keep this field in the final version? we can add it while debugging if needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nit: should we keep this field in the final version? we can add it while debugging if needed

I can remove it. Besides, this symbol is always the same object as the one that the Lint instance was created with, so if debugging were a concern, a better place to store it would be with the Lint instance anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unused field removed in 1f1247b.

Span span, // declaration's lexical range
Lint lint, // the Lint configuration that applies at this declaration
Symbol symbol, // declaration symbol (for debug purposes only; null for root)
List<LintRange> children // the nested declarations one level below this node
Copy link
Contributor

@vicente-romero-oracle vicente-romero-oracle Aug 13, 2025

Choose a reason for hiding this comment

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

not a proposal to do any change, but I think that if instead of having a tree-like structure in which each range has, potentially, a number of children, we had one list of ranges sorted by its starting point. I think that we could find the right range doing a binary search. We could actually have both: the current tree and a flat list of lint ranges for searches. Again probably not necessary for general cases but there could be corner cases as in machine generated code for which having a faster retrieval could make the difference. But again we can do that if needed in the future

Copy link
Contributor Author

@archiecobbs archiecobbs Aug 13, 2025

Choose a reason for hiding this comment

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

I think at one point I had something like that, but it made things more complicated. Plain binary search doesn't work when you are searching in a list of (possibly nested) intervals instead of a list of points, because there can be multiple matches (arbitrarily many in fact). I think it would require an Interval tree.

There is also another annoying detail, which is that the nesting is not always proper: in some oddball cases (none of which I can specifically remember) there can be an AST node whose starting position is before the starting position of its parent AST node (or ending position after its parent). These instances could cause an Interval tree type of algorithm to glitch out.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, interesting that you explored those options. Yes I also saw the interval tree solution but that seemed like an overkill, at least as an starting point.

@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Aug 14, 2025
@archiecobbs
Copy link
Contributor Author

@vicente-romero-oracle thanks for the re-review.

@lahodaj @mcimadamore please re-review after 1f1247b whenever convenient.

Thanks!

Copy link
Contributor

@mcimadamore mcimadamore left a comment

Choose a reason for hiding this comment

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

Still looks good to me :-)

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Aug 20, 2025
@archiecobbs
Copy link
Contributor Author

/integrate

@openjdk
Copy link

openjdk bot commented Aug 20, 2025

Going to push as commit 3e60ab5.
Since your change was applied there have been 111 commits pushed to the master branch:

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Aug 20, 2025
@openjdk openjdk bot closed this Aug 20, 2025
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Aug 20, 2025
@openjdk
Copy link

openjdk bot commented Aug 20, 2025

@archiecobbs Pushed as commit 3e60ab5.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@mcimadamore
Copy link
Contributor

Thanks @archiecobbs for all your hard work on this issue. I'm glad to see this integrated!

@archiecobbs
Copy link
Contributor Author

@mcimadamore thanks very much for your reviews and helpful discussions. "Cleanups" like this are sometimes tedious to review so I appreciate your time on it!

@Stephan202
Copy link

Stephan202 commented Sep 20, 2025

This PR fixes an issue that impacts JDK 25. See openrewrite/rewrite-templating#165 for details. Can/will it be backported for inclusion in JDK 25.0.1?

(Asking here, as I don't have an account at https://bugs.openjdk.org/. Let me know if there's a better/preferred channel.)

@archiecobbs
Copy link
Contributor Author

@Stephan202,

I took at look at the openrewrite issue but it's not specific on what the actual bug is. Also, this PR was mostly a refactoring so that doesn't clarify it either. Do you have a small reproducer test case that demonstrates the bug?

@Stephan202
Copy link

Hey @archiecobbs! I used the reproducer in openrewrite/rewrite-templating#165 to git bisect my way to the commits that introduced and then resolved the issue (by building the JDK at a specific revision, then manually checking whether the build failed with export JAVA_HOME=/tmp/jdk/build/linux-x86_64-server-release/jdk).

The actual bug is described here: "somehow" when OpenRewrite's annotation processor is active, javac reports unchecked and deprecation warnings, despite occurring in a @SuppressWarnings scope. I only briefly looked around with a debugger, but was not familiar enough with JDK internals to quickly understand what happens.

I'm currently working on a much smaller reproduction case; I'll post here once done.

@Stephan202
Copy link

Alright, run the following script in an empty directory to create a pom.xml and src/main/java/com/example/Reproducer.java:

#!/usr/bin/env bash

set -euo pipefail

# Creates files in the current directory to reproduce the issue.
# This script writes `pom.xml` and `src/main/java/com/example/Reproducer.java`.

mkdir -p src/main/java/com/example

cat > pom.xml <<'POM_EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>reproducer</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.google.errorprone</groupId>
                <artifactId>error_prone_core</artifactId>
                <version>2.42.0</version>
            </dependency>
            <dependency>
                <groupId>javax.annotation</groupId>
                <artifactId>javax.annotation-api</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.assertj</groupId>
                <artifactId>assertj-bom</artifactId>
                <version>3.27.4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.openrewrite.recipe</groupId>
                <artifactId>rewrite-recipe-bom</artifactId>
                <version>3.14.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.google.errorprone</groupId>
            <artifactId>error_prone_core</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.openrewrite</groupId>
            <artifactId>rewrite-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.openrewrite</groupId>
            <artifactId>rewrite-templating</artifactId>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.14.0</version>
					<configuration>
						<compilerArgs>
							<arg>-Xlint:all</arg>
						</compilerArgs>
						<parameters>true</parameters>
						<release>17</release>
						<showWarnings>true</showWarnings>
						<failOnWarning>true</failOnWarning>
					</configuration>
				</plugin>
			</plugins>
        </pluginManagement>
    </build>

    <profiles>
        <profile>
            <id>break-it</id>
    		<build>
				<pluginManagement>
					<plugins>
						<plugin>
							<groupId>org.apache.maven.plugins</groupId>
							<artifactId>maven-compiler-plugin</artifactId>
							<configuration>
								<annotationProcessorPaths>
									<path>
										<groupId>org.openrewrite</groupId>
										<artifactId>rewrite-templating</artifactId>
									</path>
								</annotationProcessorPaths>
							</configuration>
						</plugin>
					</plugins>
				</pluginManagement>
    		</build>
        </profile>
    </profiles>
</project>
POM_EOF

cat > src/main/java/com/example/Reproducer.java <<'JAVA_EOF'
package com.example;

import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import org.assertj.core.api.AbstractThrowableAssert;

final class Reproducer {
  // XXX: This rule changes the `Throwable` against which subsequent assertions are made.
  static final class AbstractThrowableAssertCauseIsSameAs {
    @BeforeTemplate
    @SuppressWarnings("deprecation" /* This deprecated API will be rewritten. */)
    AbstractThrowableAssert<?, ? extends Throwable> before(
        AbstractThrowableAssert<?, ? extends Throwable> throwableAssert, Throwable expected) {
      return throwableAssert.hasCauseReference(expected);
    }

    @AfterTemplate
    AbstractThrowableAssert<?, ? extends Throwable> after(
        AbstractThrowableAssert<?, ? extends Throwable> throwableAssert, Throwable expected) {
      return throwableAssert.cause().isSameAs(expected);
    }
  }
}
JAVA_EOF

With JDK 25, the build passes when running mvn clean compile, but fails when running mvn clean compile -Pbreak-it:

...
[INFO] --- compiler:3.14.0:compile (default-compile) @ reproducer ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 1 source file with javac [debug parameters release 17] to target/classes
[INFO] -------------------------------------------------------------
[WARNING] COMPILATION WARNING : 
[INFO] -------------------------------------------------------------
[WARNING] /tmp/_/src/main/java/com/example/Reproducer.java:[14,29] hasCauseReference(java.lang.Throwable) in org.assertj.core.api.AbstractThrowableAssert has been deprecated
[INFO] 1 warning
[INFO] -------------------------------------------------------------
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] warnings found and -Werror specified
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
...

With JDK 24 and below (and the latest JDK 26 EA build) the build correctly passes with both commands.

@archiecobbs
Copy link
Contributor Author

Hi @Stephan202,
This annotation processor is importing internal javac classes that are not guaranteed to provide stable API's. So this problem is likely a result of these API's changing in the refactoring associated with this PR. To confirm that, try recompiling the annotation processor against JDK 25 (just released) - the reproducer should no longer work. To state the obvious, the reason internal API's are not supported is to allow for refactoring; they're kept stable only on a "best effort" basis.

On the other hand, if you can reproduce the problem using only code that depends on supported APIs, then that would indeed be a bug and we'll track it down. That certainly could also be the case here (I haven't tried to determine that). Thanks.

@lahodaj
Copy link
Contributor

lahodaj commented Sep 22, 2025

I am afraid I need to be even more strict: internal "APIs" are not supported, and are not kept stable. Any use of such "APIs" is not recommended, and it is solely up to the user to handle any updates/changes.

My wild guess here is that openrewrite tries to suppress diagnostics (so that it can attribute the template without producing anything), but that fails for some reason (although I admit I don't immediately see the reason). It is hard to say, as the code simply ignores all exceptions:
https://github.com/openrewrite/rewrite-templating/blob/02cc7b03b9ef8eea0c609866bf0788d08731deb6/src/main/java/org/openrewrite/java/template/internal/CompilerMessageSuppressor.java#L127
And since this PR moves the warning reporting a to later point, it appears to work after this PR.

Also, for completeness, code like this:
https://github.com/openrewrite/rewrite-templating/blob/02cc7b03b9ef8eea0c609866bf0788d08731deb6/src/main/java/org/openrewrite/java/template/processor/TypeAwareProcessor.java#L138
is basically guaranteed to stop working at some point:
https://openjdk.org/jeps/498

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

5 participants