Add support for specifying badEnclosingTypes for BadImport via flags#4228
Add support for specifying badEnclosingTypes for BadImport via flags#4228hisener wants to merge 2 commits intogoogle:masterfrom
BadImport via flags#4228Conversation
| @Test | ||
| public void badEnclosingTypes_staticMethod() { | ||
| compilationTestHelper | ||
| .setArgs("-XepOpt:BadImport:BadEnclosingTypes=com.google.common.collect.ImmutableList") | ||
| .addSourceLines( | ||
| "Test.java", | ||
| "import static com.google.common.collect.ImmutableList.toImmutableList;", | ||
| "import com.google.common.collect.ImmutableList;", | ||
| "import java.util.stream.Collector;", | ||
| "", | ||
| "class Test {", | ||
| " // BUG: Diagnostic contains: ImmutableList.toImmutableList()", | ||
| " Collector<?, ?, ImmutableList<Object>> immutableList = toImmutableList();", |
There was a problem hiding this comment.
Is disallowing static import desirable? Should we change the behavior only for nested types? 🤔
There was a problem hiding this comment.
The current behaviour of treating static imports consistently seems OK to me. Obviously toImmutableList is just an example, in general if com.example.Foo is supposed to provide a namespace and not have its members be imports, it seems OK to discourage both import com.example.Foo.Bar and import static com.example.Foo.baz.
cushon
left a comment
There was a problem hiding this comment.
LGTM aside from the comment about Tree#toString. Thanks for the PR!
| return; | ||
| } | ||
| if (BadImport.BAD_NESTED_CLASSES.contains(tree.getIdentifier().toString())) { | ||
| if (exemptedTypes.contains(tree.getExpression().toString()) |
There was a problem hiding this comment.
I think this is fine because of the guarantees made by the checks in isFullyQualified, but we generally try to avoid using Tree#toString. There's some performance cost for larger trees, and the string representation isn't stable.
What do you think about something like:
if (!BadImport.BAD_NESTED_CLASSES.contains(tree.getIdentifier().toString())) {
return;
}
if (!(tree.getExpression() instanceof MemberSelectTree)) {
return;
}
Symbol sym = getSymbol(tree.getExpression());
if (!(sym instanceof ClassSymbol)) {
return;
}
if (exemptedTypes.contains(((ClassSymbol) sym).getQualifiedName().toString())) {
return;
}
handle(new TreePath(path, tree.getExpression()));There was a problem hiding this comment.
👀 We shouldn't directly return if it's not a bad nested class, but I think I got your point.
I tried to refactor in 67aa36d, PTAL.
| @Test | ||
| public void badEnclosingTypes_staticMethod() { | ||
| compilationTestHelper | ||
| .setArgs("-XepOpt:BadImport:BadEnclosingTypes=com.google.common.collect.ImmutableList") | ||
| .addSourceLines( | ||
| "Test.java", | ||
| "import static com.google.common.collect.ImmutableList.toImmutableList;", | ||
| "import com.google.common.collect.ImmutableList;", | ||
| "import java.util.stream.Collector;", | ||
| "", | ||
| "class Test {", | ||
| " // BUG: Diagnostic contains: ImmutableList.toImmutableList()", | ||
| " Collector<?, ?, ImmutableList<Object>> immutableList = toImmutableList();", |
There was a problem hiding this comment.
The current behaviour of treating static imports consistently seems OK to me. Obviously toImmutableList is just an example, in general if com.example.Foo is supposed to provide a namespace and not have its members be imports, it seems OK to discourage both import com.example.Foo.Bar and import static com.example.Foo.baz.
| return BadImport.BAD_NESTED_CLASSES.contains(tree.getIdentifier().toString()); | ||
| } | ||
|
|
||
| private boolean isExemptedEnclosingType(MemberSelectTree tree) { |
There was a problem hiding this comment.
Does it make sense to early-exit if the flag is not set? Or, is the cost negligible? 🤔
| private boolean isExemptedEnclosingType(MemberSelectTree tree) { | |
| private boolean isExemptedEnclosingType(MemberSelectTree tree) { | |
| if (exemptedEnclosingTypes.isEmpty()) { | |
| return false; | |
| } |
There was a problem hiding this comment.
Either way is fine with me, I think the cost is probably negligible.
There was a problem hiding this comment.
Leaving it as-is then 👍
Following the discussions in #2236, this PR introduces the `BadImport:BadEnclosingTypes` flag to disallow nested types of specified enclosing type. This PR also takes the flag into account in `UnnecessarilyFullyQualified` to suggest importing `EnclosingType.NestedType` when possible. For instance, when `-XepOpt:BadImport:BadEnclosingTypes=org.immutables.value.Value` is set, it would suggest the following: ```java final class Test { @org.immutables.value.Value.Immutable abstract class AbstractType {} } ``` -> ```java final class Test { @Value.Immutable abstract class AbstractType {} } ``` Also, it won't require suppressing `UnnecessarilyFullyQualified` in the example in #2236. ```java import org.springframework.beans.factory.annotation.Value; final class Test { Demo(@value("some.property") String property) {} @org.immutables.value.Value.Immutable abstract class AbstractType {} } ``` Closes #2236. Fixes #4228 FUTURE_COPYBARA_INTEGRATE_REVIEW=#4228 from hisener:halil.sener/bad-import-bad-enclosing-types 67aa36d PiperOrigin-RevId: 595179563
Following the discussions in #2236, this PR introduces the `BadImport:BadEnclosingTypes` flag to disallow nested types of specified enclosing type. This PR also takes the flag into account in `UnnecessarilyFullyQualified` to suggest importing `EnclosingType.NestedType` when possible. For instance, when `-XepOpt:BadImport:BadEnclosingTypes=org.immutables.value.Value` is set, it would suggest the following: ```java final class Test { @org.immutables.value.Value.Immutable abstract class AbstractType {} } ``` -> ```java final class Test { @Value.Immutable abstract class AbstractType {} } ``` Also, it won't require suppressing `UnnecessarilyFullyQualified` in the example in #2236. ```java import org.springframework.beans.factory.annotation.Value; final class Test { Demo(@value("some.property") String property) {} @org.immutables.value.Value.Immutable abstract class AbstractType {} } ``` Closes #2236. Fixes #4228 FUTURE_COPYBARA_INTEGRATE_REVIEW=#4228 from hisener:halil.sener/bad-import-bad-enclosing-types 67aa36d PiperOrigin-RevId: 595179563
Following the discussions in #2236, this PR introduces the
BadImport:BadEnclosingTypesflag to disallow nested types of specified enclosing type.This PR also takes the flag into account in
UnnecessarilyFullyQualifiedto suggest importingEnclosingType.NestedTypewhen possible.For instance, when
-XepOpt:BadImport:BadEnclosingTypes=org.immutables.value.Valueis set, it would suggest the following:->
Also, it won't require suppressing
UnnecessarilyFullyQualifiedin the example in #2236.Closes #2236.