Skip to content

Commit

Permalink
fix:Set the type of a parameter declared in a lambda to Object instea…
Browse files Browse the repository at this point in the history
…d of ommitting them when unknown. (#1108)

* Set the type of a parameter declared in a lambda to Object if unknown.

* Added some tests.
  • Loading branch information
msteinbeck authored and surli committed Jan 11, 2017
1 parent 41b2895 commit 21657c6
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 13 deletions.
9 changes: 5 additions & 4 deletions src/main/java/spoon/reflect/factory/ExecutableFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ public <T> CtExecutableReference<T> createReference(CtExecutable<T> e) {
CtTypeReference<?> refs[] = new CtTypeReference[e.getParameters().size()];
int i = 0;
for (CtParameter<?> param : e.getParameters()) {
if (param.getType() != null) {
// With a lambda and in noclasspath (when the type of parameters isn't specified), we don't have a type.
refs[i++] = param.getType().clone();
}
refs[i++] = param.getType() != null
? param.getType().clone()
// With a lambda and in noclasspath (when the type of
// parameters isn't specified), we assume Object.
: factory.Type().OBJECT.clone();
}
String executableName = e.getSimpleName();
if (e instanceof CtMethod) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,11 @@ <T> CtVariableAccess<T> createVariableAccessNoClasspath(SingleNameReference sing
@SuppressWarnings("unchecked")
final List<CtParameter<?>> parametersOfExecutable = executable.getParameters();
for (CtParameter<?> parameter : parametersOfExecutable) {
if (parameter.getType() != null) {
parameterTypesOfExecutable.add(parameter.getType().clone());
} else {
// it's the best match :(
parameterTypesOfExecutable.add(typeFactory.OBJECT);
}
parameterTypesOfExecutable.add(parameter.getType() != null
? parameter.getType().clone()
// it's the best match :(
: typeFactory.OBJECT.clone()
);
}

// find executable's corresponding jdt element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -942,9 +942,11 @@ public CtExecutableReference<?> getLambdaExecutableReference(SingleNameReference
List<CtTypeReference<?>> parametersType = new ArrayList<>();
List<CtParameter<?>> parameters = ctLambda.getParameters();
for (CtParameter<?> parameter : parameters) {
if (parameter.getType() != null) {
parametersType.add(parameter.getType().clone());
}
parametersType.add(parameter.getType() != null
? parameter.getType().clone()
// it's the best match :(
: jdtTreeBuilder.getFactory().Type().OBJECT.clone()
);
}
return jdtTreeBuilder.getFactory().Executable().createReference(declaringType, ctLambda.getType(), ctLambda.getSimpleName(), parametersType);
}
Expand Down
57 changes: 57 additions & 0 deletions src/test/java/spoon/test/parameters/ParameterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.reference.CtParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.filter.NameFilter;
import spoon.reflect.visitor.filter.TypeFilter;

Expand Down Expand Up @@ -60,4 +61,60 @@ public boolean matches(CtParameterReference element) {
assertEquals(ctParameter.getReference(), element);
}
}

@Test
@SuppressWarnings("unchecked")
public void testMultiParameterLambdaTypeReference() {
Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/resources/noclasspath/lambdas/MultiParameterLambda.java");
launcher.getEnvironment().setNoClasspath(true);
launcher.buildModel();

List<CtParameter> parameters;

// test string parameters
parameters = launcher.getModel()
.getElements(new NameFilter<CtMethod>("stringLambda"))
.get(0)
.getElements(new TypeFilter<>(CtParameter.class));
assertEquals(2, parameters.size());
for (final CtParameter param : parameters) {
for (final CtTypeReference refType :
(List<CtTypeReference>) param.getReference()
.getDeclaringExecutable()
.getParameters()) {
assertEquals(launcher.getFactory().Type().STRING, refType);
}
}

// test integer parameters
parameters = launcher.getModel()
.getElements(new NameFilter<CtMethod>("integerLambda"))
.get(0)
.getElements(new TypeFilter<>(CtParameter.class));
assertEquals(2, parameters.size());
for (final CtParameter param : parameters) {
for (final CtTypeReference refType :
(List<CtTypeReference>) param.getReference()
.getDeclaringExecutable()
.getParameters()) {
assertEquals(launcher.getFactory().Type().INTEGER, refType);
}
}

// test unknown parameters
parameters = launcher.getModel()
.getElements(new NameFilter<CtMethod>("unknownLambda"))
.get(0)
.getElements(new TypeFilter<>(CtParameter.class));
assertEquals(2, parameters.size());
for (final CtParameter param : parameters) {
for (final CtTypeReference refType :
(List<CtTypeReference>) param.getReference()
.getDeclaringExecutable()
.getParameters()) {
assertEquals(launcher.getFactory().Type().OBJECT, refType);
}
}
}
}
31 changes: 31 additions & 0 deletions src/test/resources/noclasspath/lambdas/MultiParameterLambda.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import java.util.Map;
import java.util.HashMap;

import test.Unknown;

public class MultiParameterLambda {

public void stringLambda() {
final Map<String, String> map = new HashMap<>();
map.put("a", "A");
map.put("b", "B");
map.put("c", "C");
map.forEach((key, value) -> System.out.println(key + ", " + value));
}

public void integerLambda() {
final Map<Integer, Integer> map = new HashMap<>();
map.put(1, 100);
map.put(2, 200);
map.put(3, 300);
map.forEach((key, value) -> System.out.println(key + ", " + value));
}

public void unknownLambda() {
final Map<Unknown, Unknown> map = new HashMap<>();
map.put(new Unknown(), new Unknown());
map.put(new Unknown(), new Unknown());
map.put(new Unknown(), new Unknown());
map.forEach((key, value) -> System.out.println(key + ", " + value));
}
}

0 comments on commit 21657c6

Please sign in to comment.