Custom check - check if method reference is called

35 views
Skip to first unread message

Maarten Naberink

unread,
Mar 15, 2022, 9:26:13 AM3/15/22
to error-prone-discuss
I'm working on a custom check, to make sure a call to `initialResult()` is done whenever a call to `updates()` is done on the same symbol. Most of the check works fine but I have trouble with method references. I based my check hugely on ByteBufferBackingArray check that is already in errorprone.

example code in test ; 

// CORRECT
Mono.defer(() -> Mono.just(queryGateway.subscriptionQuery(
new Object(), Void.class, Object.class)))
.doOnNext(SubscriptionQueryResult::initialResult)
.flatMapMany(SubscriptionQueryResult::updates);

// INCORRECT
Mono.defer(() -> Mono.just(queryGateway.subscriptionQuery(
new Object(), Void.class, Object.class)))
// BUG: Diagnostic matches: X
.flatMapMany(SubscriptionQueryResult::updates);  


the part of the code to check this;
@Override 
matchMemberReference(){
...
if (updateSymbol instanceof ClassSymbol) {
MethodTree enclosingMethod = ASTHelpers.findEnclosingMethod(state);
if (enclosingMethod == null || ValidSubscriptionQueryScanner.scan(enclosingMethod,
state,
updateSymbol)
) {
return Description.NO_MATCH;
}
}
}
....
private static class ValidSubscriptionQueryScanner extends TreeScanner<Void, VisitorState> {

private final Symbol searchedUpdateSymbol;
private boolean valid;


private ValidSubscriptionQueryScanner(Symbol searchedUpdateSymbol) {
this.searchedUpdateSymbol = searchedUpdateSymbol;
}

static boolean scan(Tree tree, VisitorState state, Symbol searchedBufferSymbol) {
ValidSubscriptionQueryScanner visitor = new ValidSubscriptionQueryScanner(
searchedBufferSymbol);
tree.accept(visitor, state);
return visitor.valid;
}

@Override
public Void visitMethodInvocation(MethodInvocationTree tree, VisitorState state) {
return matches(tree, state) ? null : super.visitMethodInvocation(tree, state);
}

@Override
public Void visitMemberReference(MemberReferenceTree tree, VisitorState state) {
return matches(tree, state) ? null :super.visitMemberReference(tree,state);
}


private boolean matches(ExpressionTree tree, VisitorState state) {
if (valid) {
return true;
}
Symbol updateSymbol = ASTHelpers.getSymbol(ASTHelpers.getReceiver(tree));

if (searchedUpdateSymbol.equals(updateSymbol) && SQ_INITIALRESULT_MATCHER.matches(tree,
state)) {
valid = true;
}
return false;
}
}

The problem is that the updates() in the incorrect piece is mapping to the initialResult in the correct one. How can I make sure that these are compared separately and that the test will fail.   
Reply all
Reply to author
Forward
0 new messages