-
Notifications
You must be signed in to change notification settings - Fork 109
Recipes to find ThreadLocals and determine their mutation
#875
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
Conversation
|
needs another round of personal review, but open for comments. |
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/FindThreadLocalsMutableFromOutside.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/threadlocal/AbstractFindThreadLocals.java
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Outdated
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/AbstractFindThreadLocals.java
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/threadlocal/FindNeverMutatedThreadLocals.java
Show resolved
Hide resolved
...java/org/openrewrite/java/migrate/search/threadlocal/FindThreadLocalsMutableFromOutside.java
Show resolved
Hide resolved
.../openrewrite/java/migrate/search/threadlocal/FindThreadLocalsMutatedOnlyInDefiningScope.java
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/migrate/search/threadlocal/AbstractFindThreadLocals.java
Show resolved
Hide resolved
- Moved ThreadLocalTable from search/ to table/ package to align with repository conventions - Added data table verification tests to all four ThreadLocal recipe test files - Updated import in AbstractFindThreadLocals to use new package location
| } | ||
|
|
||
| public static class ThreadLocalInfo { | ||
| private @Nullable Path declarationPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private @Nullable Path declarationPath; | |
| private @Nullable Path declarationPath; | |
| assertThat(rows.get(0).getClassName()).isEqualTo("com.example.Holder"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("com.example.Holder"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("com.example.Holder"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Never mutated"); |
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | ||
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | ||
| assertThat(rows.get(0).getModifiers()).isEqualTo("static final"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.get(0).getModifiers()).isEqualTo("static final"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("Example"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.getFirst().getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.getFirst().getModifiers()).isEqualTo("static final"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Never mutated"); |
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("PUBLIC_TL"); | ||
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("public"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Potentially mutable"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("PUBLIC_TL"); | |
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("public"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Potentially mutable"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("Example"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("PUBLIC_TL"); | |
| assertThat(rows.getFirst().getAccessModifier()).isEqualTo("public"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Potentially mutable"); |
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | ||
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Mutated only in initialization"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Mutated only in initialization"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("Example"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.getFirst().getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Mutated only in initialization"); |
| } | ||
|
|
||
| public static class ThreadLocalInfo { | ||
| private @Nullable Path declarationPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private @Nullable Path declarationPath; | |
| private @Nullable Path declarationPath; | |
| assertThat(rows.get(0).getClassName()).isEqualTo("com.example.Holder"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("com.example.Holder"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("com.example.Holder"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Never mutated"); |
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | ||
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | ||
| assertThat(rows.get(0).getModifiers()).isEqualTo("static final"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.get(0).getModifiers()).isEqualTo("static final"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Never mutated"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("Example"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.getFirst().getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.getFirst().getModifiers()).isEqualTo("static final"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Never mutated"); |
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("PUBLIC_TL"); | ||
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("public"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Potentially mutable"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("PUBLIC_TL"); | |
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("public"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Potentially mutable"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("Example"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("PUBLIC_TL"); | |
| assertThat(rows.getFirst().getAccessModifier()).isEqualTo("public"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Potentially mutable"); |
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | ||
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | ||
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | ||
| assertThat(rows.get(0).getMutationType()).isEqualTo("Mutated only in initialization"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assertThat(rows.get(0).getClassName()).isEqualTo("Example"); | |
| assertThat(rows.get(0).getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.get(0).getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.get(0).getMutationType()).isEqualTo("Mutated only in initialization"); | |
| assertThat(rows.getFirst().getClassName()).isEqualTo("Example"); | |
| assertThat(rows.getFirst().getFieldName()).isEqualTo("TL"); | |
| assertThat(rows.getFirst().getAccessModifier()).isEqualTo("private"); | |
| assertThat(rows.getFirst().getMutationType()).isEqualTo("Mutated only in initialization"); |
|
@timtebeek, I will close this PR and move it over to my personal GitHub. I feel it's more of a demo than a recipe we want in the official catalog. |
What's changed?
This PR introduces a comprehensive suite of search recipes to identify
ThreadLocalvariables that could be migrated toScopedValuein Java 25+ (JEP 506):What's your motivation?
Java 25 introduces
ScopedValueas a modern alternative toThreadLocalfor immutable thread-local values, offering:Unfortunately not all
ThreadLocalinstances qualify equally.These recipes help development teams:
Anything in particular you'd like reviewers to focus on?
AbstractFindThreadLocalsbase class uses scanning to detect mutations across multiple compilation units. Please verify this correctly handles all edge cases.Anyone you would like to review specifically?
Have you considered any alternatives or workarounds?
Any additional context
Checklist