Skip to content

Commit

Permalink
Make MethodMatcher more lightweight
Browse files Browse the repository at this point in the history
  • Loading branch information
knutwannheden committed Feb 23, 2024
1 parent 295b0b2 commit e0265af
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,30 @@ public void test() {
)
);
}

@Test
void fullyQualifiedStaticMemberReference() {
rewriteRun(
spec -> spec.recipe(new ChangeMethodName("com.abc.B static1(String)", "static2", null, null)),
java(b, SourceSpec::skip),
java(
"""
package com.abc;
class A {
public void test() {
com.abc.B.static1("boo");
}
}
""",
"""
package com.abc;
class A {
public void test() {
com.abc.B.static2("boo");
}
}
"""
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public J.MemberReference visitMemberReference(J.MemberReference memberRef, Execu
@Override
public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
J.FieldAccess f = super.visitFieldAccess(fieldAccess, ctx);
if (methodMatcher.isFullyQualifiedClassReference(f)) {
if (getCursor().getParentTreeCursor().getValue() instanceof J.Import && methodMatcher.isFullyQualifiedClassReference(f)) {
Expression target = f.getTarget();
if (target instanceof J.FieldAccess) {
String className = target.printTrimmed(getCursor());
Expand Down
68 changes: 45 additions & 23 deletions rewrite-java/src/main/java/org/openrewrite/java/MethodMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.joining;
import static java.util.Objects.requireNonNull;
import static org.openrewrite.java.tree.TypeUtils.fullyQualifiedNamesAreEqual;

/**
Expand Down Expand Up @@ -62,10 +62,10 @@ public class MethodMatcher {
private static final String ASPECTJ_DOT_PATTERN = StringUtils.aspectjNameToPattern(".");
private static final String ASPECTJ_DOTDOT_PATTERN = StringUtils.aspectjNameToPattern("..");

@Getter
@Nullable
private Pattern targetTypePattern;

@Getter
@Nullable
private Pattern methodNamePattern;

@Getter
Expand Down Expand Up @@ -98,15 +98,22 @@ public MethodMatcher(String signature, boolean matchOverrides) {
public Void visitMethodPattern(MethodSignatureParser.MethodPatternContext ctx) {
MethodSignatureParser.TargetTypePatternContext targetTypePatternContext = ctx.targetTypePattern();
String pattern = new TypeVisitor().visitTargetTypePattern(targetTypePatternContext);
targetTypePattern = Pattern.compile(new TypeVisitor().visitTargetTypePattern(targetTypePatternContext));
targetType = isPlainIdentifier(targetTypePatternContext)
? pattern.replace(ASPECTJ_DOT_PATTERN, ".").replace("\\", "")
: null;
pattern = ctx.simpleNamePattern().children.stream()
.map(c -> StringUtils.aspectjNameToPattern(c.toString()))
.collect(joining(""));
methodNamePattern = Pattern.compile(pattern);
methodName = isPlainIdentifier(ctx.simpleNamePattern()) ? pattern : null;
if (isPlainIdentifier(targetTypePatternContext)) {
targetType = pattern.replace(ASPECTJ_DOT_PATTERN, ".").replace("\\", "");
} else {
targetTypePattern = Pattern.compile(pattern);
}

StringBuilder builder = new StringBuilder();
for (ParseTree child : ctx.simpleNamePattern().children) {
builder.append(StringUtils.aspectjNameToPattern(child.getText()));
}
if (isPlainIdentifier(ctx.simpleNamePattern())) {
methodName = builder.toString();
} else {
methodNamePattern = Pattern.compile(builder.toString());
}

argumentPattern = Pattern.compile(new FormalParameterVisitor().visitFormalParametersPattern(
ctx.formalParametersPattern()));
return null;
Expand Down Expand Up @@ -142,9 +149,17 @@ public MethodMatcher(JavaType.Method method) {
this(methodPattern(method), false);
}

public String getTargetTypePattern() {
return targetTypePattern != null ? targetTypePattern.pattern() : requireNonNull(targetType);
}

public String getMethodNamePattern() {
return methodNamePattern != null ? methodNamePattern.pattern() : requireNonNull(methodName);
}

private boolean matchesTargetTypeName(String fullyQualifiedTypeName) {
return this.targetType != null && fullyQualifiedNamesAreEqual(this.targetType, fullyQualifiedTypeName) ||
this.targetType == null && this.targetTypePattern.matcher(fullyQualifiedTypeName).matches();
this.targetTypePattern != null && this.targetTypePattern.matcher(fullyQualifiedTypeName).matches();
}

boolean matchesTargetType(@Nullable JavaType.FullyQualified type) {
Expand All @@ -158,7 +173,7 @@ boolean matchesTargetType(@Nullable JavaType.FullyQualified type) {
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean matchesMethodName(String methodName) {
return this.methodName != null && this.methodName.equals(methodName) ||
this.methodName == null && methodNamePattern.matcher(methodName).matches();
this.methodNamePattern != null && methodNamePattern.matcher(methodName).matches();
}

private boolean matchesParameterTypes(List<JavaType> parameterTypes) {
Expand Down Expand Up @@ -205,7 +220,7 @@ public boolean matches(J.MethodDeclaration method, J.ClassDeclaration enclosing)

// aspectJUtils does not support matching classes separated by packages.
// [^.]* is the product of a fully wild card match for a method. `* foo()`
boolean matchesTargetType = (targetType == null && "[^.]*".equals(targetTypePattern.pattern()))
boolean matchesTargetType = (targetTypePattern != null && "[^.]*".equals(targetTypePattern.pattern()))
|| matchesTargetType(enclosing.getType());
if (!matchesTargetType) {
return false;
Expand Down Expand Up @@ -281,6 +296,7 @@ private boolean matchesSelectBySimpleNameAlone(J.Identifier select) {
if (targetType != null) {
return targetType.equals(select.getSimpleName()) || targetType.endsWith('.' + select.getSimpleName());
}
//noinspection DataFlowIssue
return targetTypePattern.matcher(select.getSimpleName()).matches() ||
Pattern.compile(targetTypePattern.pattern()
.replaceAll(".*" + Pattern.quote(ASPECTJ_DOT_PATTERN), "")
Expand Down Expand Up @@ -308,16 +324,22 @@ private String argumentsFromExpressionTypes(J.MethodInvocation method) {
*
* @param fieldAccess A J.FieldAccess that hopefully has the same fully qualified type as this matcher.
*/
@SuppressWarnings("DataFlowIssue")
public boolean isFullyQualifiedClassReference(J.FieldAccess fieldAccess) {
String hopefullyFullyQualifiedMethod;
if (targetType != null) {
hopefullyFullyQualifiedMethod = targetType + "." + methodNamePattern.pattern();
} else {
hopefullyFullyQualifiedMethod = targetTypePattern.pattern()
.replace(ASPECTJ_DOT_PATTERN, ".")
+ "." + methodNamePattern.pattern();
if (methodName != null && !methodName.equals(fieldAccess.getName().getSimpleName())) {
return false;
} else if (methodNamePattern != null && !methodNamePattern.matcher(fieldAccess.getName().getSimpleName()).matches()) {
return false;
}

Expression target = fieldAccess.getTarget();
if (target instanceof J.Identifier) {
return targetType != null && targetType.equals(((J.Identifier) target).getSimpleName()) ||
targetTypePattern != null && targetTypePattern.matcher(((J.Identifier) target).getSimpleName()).matches();
} else if (target instanceof J.FieldAccess) {
return ((J.FieldAccess) target).isFullyQualifiedClassReference(targetType != null ? targetType : targetTypePattern.pattern());
}
return fieldAccess.isFullyQualifiedClassReference(hopefullyFullyQualifiedMethod);
return false;
}

@Nullable
Expand Down

0 comments on commit e0265af

Please sign in to comment.