IG: don't produce code that can't compile in foreach quick fixes (IDEA-114183)

This commit is contained in:
Bas Leijdekkers
2018-09-06 15:45:00 +02:00
parent bead35f261
commit 96213ca337
8 changed files with 84 additions and 63 deletions
@@ -14,6 +14,7 @@ import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -1211,37 +1212,30 @@ public class ForCanBeForeachInspection extends BaseInspection {
if (!(declaredIterator instanceof PsiVariable)) {
return null;
}
final PsiVariable iteratorVariable = (PsiVariable)declaredIterator;
final PsiMethodCallExpression initializer =
(PsiMethodCallExpression)iteratorVariable.getInitializer();
final PsiVariable iterator = (PsiVariable)declaredIterator;
final PsiMethodCallExpression initializer = (PsiMethodCallExpression)iterator.getInitializer();
if (initializer == null) {
return null;
}
final PsiType iteratorType = initializer.getType();
if (iteratorType == null) {
final PsiReferenceExpression methodExpression = initializer.getMethodExpression();
final PsiExpression collection = ExpressionUtils.getQualifierOrThis(methodExpression);
final PsiType collectionType = collection.getType();
if (collectionType == null) {
return null;
}
final PsiType iteratorContentType = getContentType(iteratorType, CommonClassNames.JAVA_UTIL_ITERATOR);
final PsiType iteratorVariableType = iteratorVariable.getType();
final PsiType contentType;
final PsiClassType javaLangObject = TypeUtils.getObjectType(forStatement);
final PsiType contentType = getContentType(collectionType, CommonClassNames.JAVA_LANG_ITERABLE);
if (contentType == null) {
return null;
}
PsiType iteratorContentType = getContentType(iterator.getType(), CommonClassNames.JAVA_UTIL_ITERATOR);
if (TypeUtils.isJavaLangObject(iteratorContentType)) {
iteratorContentType = getContentType(initializer.getType(), CommonClassNames.JAVA_UTIL_ITERATOR);
}
if (iteratorContentType == null) {
final PsiType iteratorVariableContentType =
getContentType(iteratorVariableType, CommonClassNames.JAVA_UTIL_ITERATOR);
if (iteratorVariableContentType == null) {
contentType = javaLangObject;
}
else {
contentType = iteratorVariableContentType;
}
return null;
}
else {
contentType = iteratorContentType;
}
final PsiReferenceExpression methodExpression =
initializer.getMethodExpression();
final PsiExpression collection = ExpressionUtils.getQualifierOrThis(methodExpression);
final boolean isDeclaration = isIteratorNextDeclaration(firstStatement, iteratorVariable, contentType);
final boolean isDeclaration = isIteratorNextDeclaration(firstStatement, iterator, contentType);
final PsiStatement statementToSkip;
@NonNls final String finalString;
final String contentVariableName;
@@ -1285,7 +1279,7 @@ public class ForCanBeForeachInspection extends BaseInspection {
}
statementToSkip = null;
}
final String contentTypeString = contentType.getCanonicalText();
final String contentTypeString = iteratorContentType.getCanonicalText();
@NonNls final StringBuilder out = new StringBuilder();
out.append("for(");
out.append(finalString);
@@ -1293,12 +1287,12 @@ public class ForCanBeForeachInspection extends BaseInspection {
out.append(' ');
out.append(contentVariableName);
out.append(": ");
if (!contentType.equals(javaLangObject) && iteratorContentType == null) {
if (!TypeConversionUtil.isAssignable(iteratorContentType, contentType)) {
out.append('(').append("java.lang.Iterable<").append(contentTypeString).append('>').append(')');
}
out.append(collection.getText());
out.append(')');
replaceIteratorNext(body, contentVariableName, iteratorVariable, contentType, statementToSkip, out);
replaceIteratorNext(body, contentVariableName, iterator, contentType, statementToSkip, out);
return out.toString();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2018 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -130,8 +130,10 @@ public class WhileCanBeForeachInspection extends BaseInspection {
if (contentType == null) {
return;
}
final PsiType iteratorType = iterator.getType();
final PsiType iteratorContentType = ForCanBeForeachInspection.getContentType(iteratorType, "java.util.Iterator");
PsiType iteratorContentType = ForCanBeForeachInspection.getContentType(iterator.getType(), CommonClassNames.JAVA_UTIL_ITERATOR);
if (TypeUtils.isJavaLangObject(iteratorContentType)) {
iteratorContentType = ForCanBeForeachInspection.getContentType(initializer.getType(), CommonClassNames.JAVA_UTIL_ITERATOR);
}
if (iteratorContentType == null) {
return;
}
@@ -162,9 +164,10 @@ public class WhileCanBeForeachInspection extends BaseInspection {
if (JavaCodeStyleSettings.getInstance(whileStatement.getContainingFile()).GENERATE_FINAL_PARAMETERS) {
out.append("final ");
}
out.append(iteratorContentType.getCanonicalText()).append(' ').append(contentVariableName).append(": ");
final String canonicalText = iteratorContentType.getCanonicalText();
out.append(canonicalText).append(' ').append(contentVariableName).append(": ");
if (!TypeConversionUtil.isAssignable(iteratorContentType, contentType)) {
out.append("(java.lang.Iterable<").append(iteratorContentType.getCanonicalText()).append(">)");
out.append("(java.lang.Iterable<").append(canonicalText).append(">)");
}
out.append(collection.getText());
out.append(')');
@@ -185,7 +188,7 @@ public class WhileCanBeForeachInspection extends BaseInspection {
break;
}
final PsiExpression expression = assignment.getRExpression();
PsiTypeElement typeElement = iterator.getTypeElement();
final PsiTypeElement typeElement = iterator.getTypeElement();
if (typeElement.isInferredType() &&
(expression == null ||
PsiType.NULL.equals(expression.getType()) ||
@@ -0,0 +1,11 @@
import java.util.Iterator;
import java.util.List;
class RawCollection {
void m2(List ss) {
for (String s : (Iterable<String>) ss) {
"".split(s);
}
}
}
@@ -0,0 +1,12 @@
import java.util.Iterator;
import java.util.List;
class RawCollection {
void m2(List ss) {
<caret>for (Iterator<String> iterator = ss.iterator(); iterator.hasNext();) {
String s = iterator.next();
"".split(s);
}
}
}
@@ -0,0 +1,13 @@
package com.siyeh.igfixes.migration.while_can_be_foreach;
import java.util.Iterator;
import java.util.List;
class RawIterator implements Iterable {
void m(List<String> ss) {
for (String s : ss) {
System.out.println(s);
}
}
}
@@ -0,0 +1,14 @@
package com.siyeh.igfixes.migration.while_can_be_foreach;
import java.util.Iterator;
import java.util.List;
class RawIterator implements Iterable {
void m(List<String> ss) {
final Iterator iterator = ss.iterator();
while<caret> (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.siyeh.ig.fixes.migration;
import com.intellij.application.options.CodeStyle;
@@ -44,6 +30,7 @@ public class ForCanBeForeachFixTest extends IGQuickFixesTestCase {
settings.FIELD_NAME_PREFIX = oldPrefix;
}
}
public void testRawCollection() { doTest(); }
@Override
public void setUp() throws Exception {
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.siyeh.ig.fixes.migration;
import com.intellij.pom.java.LanguageLevel;
@@ -35,6 +21,7 @@ public class WhileCanBeForeachFixTest extends IGQuickFixesTestCase {
public void testUnboundWildcard() { doTest(); }
public void testVarWithoutValidInitializer() { doTest(); }
public void testVarWithValidInitializer() { doTest(); }
public void testRawIterator() { doTest(); }
@Override
protected void tuneFixture(JavaModuleFixtureBuilder builder) {