FunctionHelper: fix renaming in lambdas if autogenerated name conflicts with the existing one

This commit is contained in:
Tagir Valeev
2016-12-16 11:12:15 +07:00
parent cda8154dbc
commit 9c78db8af0
3 changed files with 60 additions and 15 deletions
@@ -34,7 +34,10 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
/**
@@ -183,6 +186,14 @@ abstract class FunctionHelper {
};
}
static boolean hasVarReference(PsiExpression expression, String name, StreamToLoopReplacementContext context) {
PsiLambdaExpression lambda = (PsiLambdaExpression)context.createExpression(name+"->"+expression.getText());
PsiParameter var = lambda.getParameterList().getParameters()[0];
PsiElement body = lambda.getBody();
LOG.assertTrue(body != null);
return ReferencesSearch.search(var, new LocalSearchScope(body)).findFirst() != null;
}
/**
* Replaces all the references to the variable {@code name} in given expression with {@code replacement}.
*
@@ -480,22 +491,15 @@ abstract class FunctionHelper {
}
void rename(String oldName, String newName, StreamToLoopReplacementContext context) {
OptionalLong idx = StreamEx.of(myParameters).indexOf(newName);
if(idx.isPresent()) {
int idx = ArrayUtil.indexOf(myParameters, newName);
if(idx >= 0) {
// If new name collides with existing parameter, rename it
for(int i = 1;; i++) {
String paramName = newName+'$'+i;
if (!paramName.equals(oldName) &&
!StreamEx.of(myParameters).has(paramName)) {
try {
myBody = replaceVarReference(myBody, newName, paramName, context);
myParameters[(int)idx.getAsLong()] = paramName;
break;
}
catch(IllegalStateException ise) {
// something is really wrong if we already have references to all newName$1, newName$2, ... newName$50
// or probably IllegalStateException was thrown by something else: at least we don't stuck in endless loop
if(i > 50) throw ise;
}
if (!paramName.equals(oldName) && !StreamEx.of(myParameters).has(paramName) && !hasVarReference(myBody, paramName, context)) {
myBody = replaceVarReference(myBody, newName, paramName, context);
myParameters[idx] = paramName;
break;
}
}
}
@@ -0,0 +1,24 @@
// "Replace Stream API chain with loop" "true"
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class Main {
public List<? extends CharSequence> getList() {
return Collections.emptyList();
}
private void collect() {
List<CharSequence> list = new ArrayList<>();
for (CharSequence charSequence : getList()) {
if (Objects.nonNull(charSequence)) {
list.add(charSequence);
}
}
List<? extends CharSequence> res = list;
System.out.println(res);
}
}
@@ -0,0 +1,17 @@
// "Replace Stream API chain with loop" "true"
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class Main {
public List<? extends CharSequence> getList() {
return Collections.emptyList();
}
private void collect() {
List<? extends CharSequence> res = getList().stream().filter(Objects::nonNull).col<caret>lect(Collectors.toList());
System.out.println(res);
}
}