Skip to content

Commit

Permalink
Handle unqualified instance method names in refaster
Browse files Browse the repository at this point in the history
Previously unqualified methods names were being handled using logic intended for local variables, which failed to match them.

Unqualified instance method names are relatively rare in templates. The motivating example was a template intended to match on an anonymous class creation, where code in the class called a method from a superclass by its simple name.

PiperOrigin-RevId: 621197168
  • Loading branch information
cushon authored and Error Prone Team committed Apr 2, 2024
1 parent 474a4ac commit e4c9409
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 0 deletions.
@@ -0,0 +1,62 @@
/*
* Copyright 2024 The Error Prone Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.errorprone.refaster;

import static com.google.errorprone.refaster.Unifier.unifications;

import com.google.auto.value.AutoValue;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.tree.JCTree.JCExpression;

/** Identifier representing an unqualified instant method. */
@AutoValue
public abstract class UMethodIdent extends UIdent {
public static UMethodIdent create(UClassIdent classIdent, CharSequence member, UType memberType) {
return new AutoValue_UMethodIdent(classIdent, StringName.of(member), memberType);
}

public static UMethodIdent create(ClassSymbol classSym, CharSequence member, UType memberType) {
return create(UClassIdent.create(classSym), member, memberType);
}

abstract UClassIdent classIdent();

@Override
public abstract StringName getName();

abstract UType memberType();

@Override
public JCExpression inline(Inliner inliner) throws CouldNotResolveImportException {
return inliner.maker().Ident(getName().inline(inliner));
}

@Override
protected Choice<Unifier> defaultAction(Tree node, Unifier unifier) {
Symbol symbol = ASTHelpers.getSymbol(node);
if (symbol != null) {
return classIdent()
.unify(symbol.getEnclosingElement(), unifier)
.thenChoose(unifications(getName(), symbol.getSimpleName()))
.thenChoose(unifications(memberType(), symbol.asType()));
}
return Choice.none();
}
}
Expand Up @@ -354,6 +354,13 @@ private UStaticIdent staticMember(Symbol symbol) {
template(symbol.asType()));
}

private UMethodIdent method(Symbol symbol) {
return UMethodIdent.create(
(ClassSymbol) symbol.getEnclosingElement(),
symbol.getSimpleName(),
template(symbol.asType()));
}

private static final UStaticIdent ANY_OF;
private static final UStaticIdent IS_INSTANCE;
private static final UStaticIdent CLAZZ;
Expand Down Expand Up @@ -622,6 +629,8 @@ public UExpression visitIdentifier(IdentifierTree tree, Void v) {
switch (sym.getKind()) {
case TYPE_PARAMETER:
return UTypeVarIdent.create(tree.getName());
case METHOD:
return method(sym);
default:
return ULocalVarIdent.create(tree.getName());
}
Expand Down
Expand Up @@ -379,4 +379,9 @@ public void typeArgumentsMethodInvocation() throws IOException {
public void memberSelectAndMethodParameterDisambiguation() throws IOException {
runTest("MemberSelectAndMethodParameterDisambiguationTemplate");
}

@Test
public void unqualifiedMethod() throws IOException {
runTest("UnqualifiedMethodTemplate");
}
}
@@ -0,0 +1,22 @@
/*
* Copyright 2024 The Error Prone Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package com.google.errorprone.refaster.testdata;

/** Test data for {@code UnqualifiedMethodTemplate}. */
public class UnqualifiedMethodTemplateExample {
public int example() {
return hashCode();
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2024 The Error Prone Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package com.google.errorprone.refaster.testdata;

import java.util.Objects;

/** Test data for {@code UnqualifiedMethodTemplate}. */
public class UnqualifiedMethodTemplateExample {
public int example() {
return Objects.hashCode(this);
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2024 The Error Prone Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.errorprone.refaster.testdata.template;

import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import java.util.Objects;

public class UnqualifiedMethodTemplate {
@BeforeTemplate
public int before() {
return hashCode();
}

@AfterTemplate
public int after() {
return Objects.hashCode(this);
}
}

0 comments on commit e4c9409

Please sign in to comment.