Skip to content

Commit

Permalink
feature: add support for Java 8 receiver parameters (#1298)
Browse files Browse the repository at this point in the history
close #1283
  • Loading branch information
surli authored and monperrus committed May 18, 2017
1 parent 71554f9 commit 399f681
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Receiver;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
Expand Down Expand Up @@ -955,6 +956,12 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
context.exit(methodDeclaration);
}

// We consider the receiver as a standard argument (i.e. as a parameter)
Receiver receiver = methodDeclaration.receiver;
if (receiver != null) {
receiver.traverse(this, methodDeclaration.scope);
}

return true;
}

Expand Down
45 changes: 43 additions & 2 deletions src/test/java/spoon/test/annotation/AnnotationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@
import java.util.List;
import java.util.Set;

import static org.hamcrest.CoreMatchers.is;

import static org.hamcrest.core.Is.is;

import static org.hamcrest.CoreMatchers.notNullValue;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
Expand Down Expand Up @@ -931,6 +934,44 @@ public void testSpoonSpoonResult() throws Exception {
assertEquals("Annotation should be @spoon.test.annotation.testclasses.PortRange", "spoon.test.annotation.testclasses.PortRange", annotation.getAnnotationType().getQualifiedName());
}

@Test
public void testGetAnnotationFromParameter() {
// contract: Java 8 receiver parameters are handled
Launcher spoon = new Launcher();
spoon.addInputResource("src/test/resources/noclasspath/Initializer.java");
String output = "target/spooned-" + this.getClass().getSimpleName() + "-firstspoon/";
spoon.setSourceOutputDirectory(output);
spoon.getEnvironment().setNoClasspath(true);
factory = spoon.getFactory();
spoon.buildModel();

List<CtMethod> methods = factory.getModel().getElements(new NameFilter<CtMethod>("setField"));
assertThat(methods.size(), is(1));

CtMethod methodSet = methods.get(0);
assertThat(methodSet.getSimpleName(), is("setField"));

List<CtParameter> parameters = methodSet.getParameters();

assertThat(parameters.size(), is(1));

CtParameter thisParameter = parameters.get(0);
assertThat(thisParameter.getSimpleName(), is("this"));


CtTypeReference thisParamType = thisParameter.getType();
assertThat(thisParamType.getSimpleName(), is("Initializer"));

List<CtAnnotation<?>> annotations = thisParameter.getType().getAnnotations();
assertThat(annotations.size(), is(2));

CtAnnotation unknownInit = annotations.get(0);
CtAnnotation raw = annotations.get(1);

assertThat(unknownInit.getAnnotationType().getSimpleName(), is("UnknownInitialization"));
assertThat(raw.getAnnotationType().getSimpleName(), is("Raw"));
}

@Test
public void annotationAddValue() {
Launcher spoon = new Launcher();
Expand All @@ -947,6 +988,6 @@ public void annotationAddValue() {
assertThat(anno1.getValue("params").getType(), is(factory.Type().createReference(String[].class)));

CtAnnotation anno = factory.Annotation().annotate(methods.get(0), TypeAnnotation.class).addValue("params", new String[0]);
assertThat(anno.getValue("params").getType(), is(factory.Type().createReference(String[].class)));
assertThat(anno.getValue("params").getType(), is(factory.Type().createReference(String[].class)));
}
}
92 changes: 92 additions & 0 deletions src/test/resources/noclasspath/Initializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import org.checkerframework.checker.initialization.qual.*;
import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.framework.qual.EnsuresQualifier;
import org.checkerframework.framework.qual.EnsuresQualifierIf;

class Initializer {

public String a;
public String b = "abc";

//:: error: (assignment.type.incompatible)
public String c = null;

public String d = ("");

public Initializer() {
//:: error: (assignment.type.incompatible)
a = null;
a = "";
c = "";
}

//:: error: (initialization.fields.uninitialized)
public Initializer(boolean foo) {}

public Initializer(int foo) {
a = "";
c = "";
}

public Initializer(float foo) {
setField();
c = "";
}

public Initializer(double foo) {
if (!setFieldMaybe()) {
a = "";
}
c = "";
}

//:: error: (initialization.fields.uninitialized)
public Initializer(double foo, boolean t) {
if (!setFieldMaybe()) {
// on this path, 'a' is not initialized
}
c = "";
}

@EnsuresQualifier(expression = "a", qualifier = NonNull.class)
public void setField(@UnknownInitialization @Raw Initializer this) {
a = "";
}

@EnsuresQualifierIf(result = true, expression = "a", qualifier = NonNull.class)
public boolean setFieldMaybe(@UnknownInitialization @Raw Initializer this) {
a = "";
return true;
}

String f = "";

void t1(@UnknownInitialization @Raw Initializer this) {
//:: error: (dereference.of.nullable)
this.f.toString();
}

String fieldF = "";
}

class SubInitializer extends Initializer {

String f = "";

void subt1(
@UnknownInitialization(Initializer.class) @Raw(Initializer.class) SubInitializer this) {
fieldF.toString();
super.f.toString();
//:: error: (dereference.of.nullable)
this.f.toString();
}

void subt2(@UnknownInitialization @Raw SubInitializer this) {
//:: error: (dereference.of.nullable)
fieldF.toString();
//:: error: (dereference.of.nullable)
super.f.toString();
//:: error: (dereference.of.nullable)
this.f.toString();
}
}

0 comments on commit 399f681

Please sign in to comment.