IDEA-167588 Uncompilable code after conversion Stream -> Loop with unknown Stream sources

This commit is contained in:
Tagir Valeev
2017-02-02 21:50:50 +03:00
parent f74272f05e
commit 803b3aa940
4 changed files with 40 additions and 7 deletions

View File

@@ -108,7 +108,10 @@ abstract class SourceOperation extends Operation {
return new ForEachSource(args[0]);
}
if (supportUnknownSources) {
return new StreamIteratorSource(call);
PsiType type = StreamApiUtil.getStreamElementType(call.getType(), false);
if (type != null) {
return new StreamIteratorSource(call, type);
}
}
return null;
}
@@ -312,10 +315,12 @@ abstract class SourceOperation extends Operation {
}
private static class StreamIteratorSource extends SourceOperation {
private final String myElementType;
private PsiMethodCallExpression myCall;
public StreamIteratorSource(PsiMethodCallExpression call) {
public StreamIteratorSource(PsiMethodCallExpression call, PsiType type) {
myCall = call;
myElementType = type.getCanonicalText();
}
@Override
@@ -355,7 +360,7 @@ abstract class SourceOperation extends Operation {
@Override
String wrap(StreamVariable outVar, String code, StreamToLoopReplacementContext context) {
String iterator = context.registerVarName(Arrays.asList("it", "iter", "iterator"));
String declaration = getIteratorType(outVar.getType()) + " " + iterator + "=" + myCall.getText() + ".iterator()";
String declaration = getIteratorType(myElementType) + " " + iterator + "=" + myCall.getText() + ".iterator()";
String condition = iterator + ".hasNext()";
return "for(" + declaration + ";" + condition + ";) {\n" +
outVar.getDeclaration(iterator + ".next()") +

View File

@@ -1,5 +1,6 @@
// "Replace Stream API chain with loop" "true"
// "Fix all 'Stream API call chain can be replaced with loop' problems in file" "true"
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -21,4 +22,17 @@ public class Test {
}
}
}
private long counter(Class<? extends Array> list) {
long count = 0L;
for (Iterator<? extends Array> it = stream(list).iterator(); it.hasNext(); ) {
Array array = it.next();
count++;
}
return count;
}
public <E> Stream<E> stream(Class<E> clazz) {
return null;
}
}

View File

@@ -1,5 +1,6 @@
// "Replace Stream API chain with loop" "true"
// "Fix all 'Stream API call chain can be replaced with loop' problems in file" "true"
import java.lang.reflect.Array;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -13,4 +14,12 @@ public class Test {
List<String> list = new Test().names().map(String::trim).filter(n -> !n.isEmpty())
.<caret>collect(Collectors.toList());
}
private long counter(Class<? extends Array> list) {
return stream(list).count();
}
public <E> Stream<E> stream(Class<E> clazz) {
return null;
}
}

View File

@@ -29,6 +29,11 @@ import org.jetbrains.annotations.Nullable;
public class StreamApiUtil {
@Contract("null -> null")
public static PsiType getStreamElementType(PsiType type) {
return getStreamElementType(type, true);
}
@Contract("null, _ -> null")
public static PsiType getStreamElementType(PsiType type, boolean variableType) {
if(!(type instanceof PsiClassType)) return null;
PsiClass aClass = ((PsiClassType)type).resolve();
if(com.intellij.psi.util.InheritanceUtil.isInheritor(aClass, false, CommonClassNames.JAVA_UTIL_STREAM_INT_STREAM)) {
@@ -44,8 +49,8 @@ public class StreamApiUtil {
return null;
}
PsiType streamType = PsiUtil.substituteTypeParameter(type, CommonClassNames.JAVA_UTIL_STREAM_STREAM, 0, false);
if(streamType instanceof PsiCapturedWildcardType) {
streamType = ((PsiCapturedWildcardType)streamType).getUpperBound();
if (variableType) {
streamType = GenericsUtil.getVariableTypeByExpressionType(streamType);
}
return streamType;
}