Skip to content

Commit

Permalink
Add support for explicit receiver parameters
Browse files Browse the repository at this point in the history
Annotated "this" arguments for instance methods and non-static nested
class constructors were added in Java 8. This special cases "this" and
"OuterClass.this" so that they are allowed as parameter names.
  • Loading branch information
jasonobrien committed Jun 4, 2020
1 parent 304176e commit a5f4f0f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/main/java/com/squareup/javapoet/ParameterSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,18 @@ static List<ParameterSpec> parametersOf(ExecutableElement method) {
return result;
}

private static boolean isValidParameterName(String name) {
// Allow "this" for explicit receiver parameters
// See https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1.
if (name.endsWith(".this")) {
return SourceVersion.isIdentifier(name.substring(0, name.length() - ".this".length()));
}
return name.equals("this") || SourceVersion.isName(name);
}

public static Builder builder(TypeName type, String name, Modifier... modifiers) {
checkNotNull(type, "type == null");
checkArgument(SourceVersion.isName(name), "not a valid name: %s", name);
checkArgument(isValidParameterName(name), "not a valid name: %s", name);
return new Builder(type, name)
.addModifiers(modifiers);
}
Expand Down
19 changes: 19 additions & 0 deletions src/test/java/com/squareup/javapoet/ParameterSpecTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ private TypeElement getElement(Class<?> clazz) {
assertThat(a.toString()).isEqualTo(b.toString());
}

@Test public void receiverParameterInstanceMethod() {
ParameterSpec.Builder builder = ParameterSpec.builder(int.class, "this");
assertThat(builder.build().name).isEqualTo("this");
}

@Test public void receiverParameterNestedClass() {
ParameterSpec.Builder builder = ParameterSpec.builder(int.class, "Foo.this");
assertThat(builder.build().name).isEqualTo("Foo.this");
}

@Test public void keywordName() {
try {
ParameterSpec.builder(int.class, "super");
fail();
} catch (Exception e) {
assertThat(e.getMessage()).isEqualTo("not a valid name: super");
}
}

@Test public void nullAnnotationsAddition() {
try {
ParameterSpec.builder(int.class, "foo").addAnnotations(null);
Expand Down

0 comments on commit a5f4f0f

Please sign in to comment.