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

LambdaMethodReference avoids suggestions for non-static methods #771

Merged
merged 3 commits into from
Aug 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -91,25 +91,31 @@ private Description checkMethodInvocation(
|| !methodInvocation.getTypeArguments().isEmpty()) {
return Description.NO_MATCH;
}
Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol(methodInvocation);
if (methodSymbol == null) {
// Should only ever occur if there are errors in the AST, allow the compiler to fail later
return Description.NO_MATCH;
}
if (!methodSymbol.isStatic()) {
// Only support static invocations for the time being to avoid erroneously
// rewriting '() -> foo()' to 'ClassName::foo' instead of 'this::foo'
// or suggesting '() -> foo.doWork().bar()' should be rewritten to 'foo.doWork()::bar',
// which executes 'doWork' eagerly, even when the supplier is not used.
return Description.NO_MATCH;
}
return buildDescription(root)
.setMessage(MESSAGE)
.addFix(buildFix(methodInvocation, root, state))
.addFix(buildFix(methodSymbol, root, state))
.build();
}

private static Optional<SuggestedFix> buildFix(
MethodInvocationTree invocation,
Symbol.MethodSymbol symbol,
LambdaExpressionTree root,
VisitorState state) {
return Optional.ofNullable(ASTHelpers.getSymbol(invocation))
// Only support static invocations for the time being to avoid erroneously
// rewriting '() -> foo()' to 'ClassName::foo' instead of 'this::foo'
.filter(Symbol::isStatic)
.flatMap(symbol -> {
SuggestedFix.Builder builder = SuggestedFix.builder();
return toMethodReference(SuggestedFixes.qualifyType(state, builder, symbol))
.map(qualified -> builder.replace(root, qualified).build());
});
SuggestedFix.Builder builder = SuggestedFix.builder();
return toMethodReference(SuggestedFixes.qualifyType(state, builder, symbol))
.map(qualified -> builder.replace(root, qualified).build());
}

private static Optional<String> toMethodReference(String qualifiedMethodName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ public void testAutoFix_block() {
}

@Test
public void testPositive_block_localMethod() {
public void testNegative_block_localMethod() {
compilationHelper.addSourceLines(
"Test.java",
"import " + ImmutableList.class.getName() + ';',
"import " + List.class.getName() + ';',
"import " + Optional.class.getName() + ';',
"class Test {",
" public List<Object> foo(Optional<List<Object>> optional) {",
" // BUG: Diagnostic contains: Lambda should be a method reference",
// A future improvement may rewrite the following to 'orElseGet(this::bar)'
" return optional.orElseGet(() -> { return bar(); });",
" }",
" private List<Object> bar() {",
Expand Down Expand Up @@ -195,15 +195,15 @@ public void testAutoFix_expression() {
}

@Test
public void testPositive_expression_localMethod() {
public void testNegative_expression_localMethod() {
compilationHelper.addSourceLines(
"Test.java",
"import " + ImmutableList.class.getName() + ';',
"import " + List.class.getName() + ';',
"import " + Optional.class.getName() + ';',
"class Test {",
" public List<Object> foo(Optional<List<Object>> optional) {",
" // BUG: Diagnostic contains: Lambda should be a method reference",
// A future improvement may rewrite the following to 'orElseGet(this::bar)'
" return optional.orElseGet(() -> bar());",
" }",
" private List<Object> bar() {",
Expand Down Expand Up @@ -258,4 +258,19 @@ public void testNegative_expression() {
" }",
"}").doTest();
}

@Test
public void testNegative_expression_chain() {
compilationHelper.addSourceLines(
"Test.java",
"import " + ImmutableList.class.getName() + ';',
"import " + Optional.class.getName() + ';',
"class Test {",
" public Object foo(Optional<Object> optional) {",
// It's important that this is not rewritten to 'optional.orElseGet(ImmutableList.of(1)::size)'
// which create a new list eagerly, and returns a supplier for the new instances 'size()' function.
" return optional.orElseGet(() -> ImmutableList.of(1).size());",
" }",
"}").doTest();
}
}
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-771.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: fix
fix:
description: LambdaMethodReference avoids suggestions for non-static methods
links:
- https://github.com/palantir/gradle-baseline/pull/771