Skip to content

Commit 7cd5def

Browse files
java-team-github-botError Prone Team
authored and
Error Prone Team
committed
Support void placeholder expressions in Refaster
PiperOrigin-RevId: 450510643
1 parent b822dd4 commit 7cd5def

File tree

6 files changed

+119
-4
lines changed

6 files changed

+119
-4
lines changed

core/src/main/java/com/google/errorprone/refaster/Template.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.sun.tools.javac.code.Type;
3838
import com.sun.tools.javac.code.Type.ForAll;
3939
import com.sun.tools.javac.code.Type.MethodType;
40+
import com.sun.tools.javac.code.TypeTag;
4041
import com.sun.tools.javac.code.Types;
4142
import com.sun.tools.javac.comp.Attr;
4243
import com.sun.tools.javac.comp.AttrContext;
@@ -139,7 +140,14 @@ protected List<Type> expectedTypes(Inliner inliner) throws CouldNotResolveImport
139140
Ordering.natural()
140141
.immutableSortedCopy(
141142
Iterables.filter(inliner.bindings.keySet(), PlaceholderExpressionKey.class))) {
142-
result.add(key.method.returnType().inline(inliner));
143+
Type type = key.method.returnType().inline(inliner);
144+
// Skip void placeholder expressions, because
145+
// a) if the expected type is void, any actual type is acceptable
146+
// b) these types are used as the argument types in a synthetic MethodType, and method
147+
// argument types cannot be void
148+
if (!type.getTag().equals(TypeTag.VOID)) {
149+
result.add(type);
150+
}
143151
}
144152
return List.from(result);
145153
}
@@ -149,7 +157,7 @@ protected List<Type> expectedTypes(Inliner inliner) throws CouldNotResolveImport
149157
* bound to the @BeforeTemplate method parameters, concatenated with the types of the expressions
150158
* bound to expression placeholders, sorted by the name of the placeholder method.
151159
*/
152-
protected List<Type> actualTypes(Inliner inliner) {
160+
protected List<Type> actualTypes(Inliner inliner) throws CouldNotResolveImportException {
153161
ArrayList<Type> result = new ArrayList<>();
154162
ImmutableList<String> argNames = expressionArgumentTypes().keySet().asList();
155163
for (int i = 0; i < expressionArgumentTypes().size(); i++) {
@@ -177,7 +185,11 @@ protected List<Type> actualTypes(Inliner inliner) {
177185
Ordering.natural()
178186
.immutableSortedCopy(
179187
Iterables.filter(inliner.bindings.keySet(), PlaceholderExpressionKey.class))) {
180-
result.add(inliner.getBinding(key).type);
188+
Type keyType = key.method.returnType().inline(inliner);
189+
// See comment in `expectedTypes` for why we skip void placeholder keys.
190+
if (!keyType.getTag().equals(TypeTag.VOID)) {
191+
result.add(inliner.getBinding(key).type);
192+
}
181193
}
182194
return List.from(result);
183195
}

core/src/main/java/com/google/errorprone/refaster/UPlaceholderExpression.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public boolean reverify(Unifier unifier) {
147147
@Override
148148
protected Choice<Unifier> defaultAction(Tree node, Unifier unifier) {
149149
// for now we only match JCExpressions
150-
if (placeholder().returnType().equals(UPrimitiveType.VOID) || !(node instanceof JCExpression)) {
150+
if (!(node instanceof JCExpression)) {
151151
return Choice.none();
152152
}
153153
JCExpression expr = (JCExpression) node;

core/src/test/java/com/google/errorprone/refaster/TemplateIntegrationTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ public void expressionPlaceholderAllowsIdentity() throws IOException {
234234
runTest("PlaceholderAllowsIdentityTemplate");
235235
}
236236

237+
@Test
238+
public void voidExpressionPlaceholder() throws IOException {
239+
runTest("VoidExpressionPlaceholderTemplate");
240+
}
241+
237242
@Test
238243
public void blockPlaceholder() throws IOException {
239244
runTest("BlockPlaceholderTemplate");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2022 The Error Prone Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.errorprone.refaster.testdata;
18+
19+
import java.util.List;
20+
21+
/** Test data for {@code VoidExpressionPlaceholderTemplate}. */
22+
public class VoidExpressionPlaceholderTemplateExample {
23+
public static void foo(String s) {
24+
s.length();
25+
}
26+
27+
public void positiveExample(List<String> list) {
28+
list.stream().forEach(x -> foo(x));
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2022 The Error Prone Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.errorprone.refaster.testdata;
18+
19+
import java.util.List;
20+
21+
/** Test data for {@code VoidExpressionPlaceholderTemplate}. */
22+
public class VoidExpressionPlaceholderTemplateExample {
23+
public static void foo(String s) {
24+
s.length();
25+
}
26+
27+
public void positiveExample(List<String> list) {
28+
list.forEach(x->foo(x));
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2022 The Error Prone Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.errorprone.refaster.testdata.template;
18+
19+
import com.google.errorprone.refaster.annotation.AfterTemplate;
20+
import com.google.errorprone.refaster.annotation.BeforeTemplate;
21+
import com.google.errorprone.refaster.annotation.Placeholder;
22+
import java.util.Collection;
23+
24+
/** Test case with a void placeholder method that is used as an expression. */
25+
public abstract class VoidExpressionPlaceholderTemplate<T> {
26+
@Placeholder
27+
abstract void consume(T t);
28+
29+
@BeforeTemplate
30+
void before(Collection<T> collection) {
31+
collection.stream().forEach(x -> consume(x));
32+
}
33+
34+
@AfterTemplate
35+
void after(Collection<T> collection) {
36+
collection.forEach(x -> consume(x));
37+
}
38+
}

0 commit comments

Comments
 (0)