Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2014-01-30 17:31:36 +01:00
16 changed files with 180 additions and 40 deletions
@@ -1765,7 +1765,7 @@ public class HighlightUtil extends HighlightUtilBase {
if (expression.getTextRange().getStartOffset() >= referencedField.getTextRange().getEndOffset()) return null;
// only simple reference can be illegal
if (expression.getQualifierExpression() != null) return null;
PsiField initField = findEnclosingFieldInitializer(expression, true);
PsiField initField = findEnclosingFieldInitializer(expression);
PsiClassInitializer classInitializer = findParentClassInitializer(expression);
if (initField == null && classInitializer == null) return null;
// instance initializers may access static fields
@@ -1786,11 +1786,6 @@ public class HighlightUtil extends HighlightUtilBase {
*/
@Nullable
public static PsiField findEnclosingFieldInitializer(@Nullable PsiElement element) {
return findEnclosingFieldInitializer(element, false);
}
@Nullable
public static PsiField findEnclosingFieldInitializer(@Nullable PsiElement element, boolean stopAtLambda) {
while (element != null) {
PsiElement parent = element.getParent();
if (parent instanceof PsiField) {
@@ -1798,7 +1793,7 @@ public class HighlightUtil extends HighlightUtilBase {
if (element == field.getInitializer()) return field;
if (field instanceof PsiEnumConstant && element == ((PsiEnumConstant)field).getArgumentList()) return field;
}
if (element instanceof PsiClass || element instanceof PsiMethod || (stopAtLambda && parent instanceof PsiLambdaExpression)) return null;
if (element instanceof PsiClass || element instanceof PsiMethod) return null;
element = parent;
}
return null;
@@ -17,10 +17,10 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -29,9 +29,12 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.hash.LinkedHashMap;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
@@ -129,7 +132,6 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
if (field != null) {
final PsiElement resolved = expression.resolve();
if (resolved instanceof PsiField &&
((PsiField)resolved).hasModifierProperty(PsiModifier.FINAL) &&
!((PsiField)resolved).hasInitializer() &&
((PsiField)resolved).getContainingClass() == field.getContainingClass()) {
bodyContainsForbiddenRefs[0] = true;
@@ -181,8 +183,8 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
final PsiMethod method = anonymousClass.getMethods()[0];
LOG.assertTrue(method != null);
final String lambdaWithTypesDeclared = composeLambdaText(method, lambdaContext, true);
final String withoutTypesDeclared = composeLambdaText(method, lambdaContext, false);
final String lambdaWithTypesDeclared = composeLambdaText(method, true);
final String withoutTypesDeclared = composeLambdaText(method, false);
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiLambdaExpression lambdaExpression =
(PsiLambdaExpression)elementFactory.createExpressionFromText(withoutTypesDeclared, anonymousClass);
@@ -202,6 +204,43 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
LOG.assertTrue(lambdaBody != null);
lambdaBody.replace(copy);
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
final Map<PsiParameter, String> names = new HashMap<PsiParameter, String>();
for (PsiParameter parameter : lambdaExpression.getParameterList().getParameters()) {
String parameterName = parameter.getName();
final String uniqueVariableName = codeStyleManager.suggestUniqueVariableName(parameterName, lambdaContext, false);
if (!Comparing.equal(parameterName, uniqueVariableName)) {
names.put(parameter, uniqueVariableName);
}
}
final LinkedHashMap<PsiElement, PsiElement> replacements = new LinkedHashMap<PsiElement, PsiElement>();
lambdaExpression.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitParameter(PsiParameter parameter) {
final String newName = names.get(parameter);
if (newName != null) {
replacements.put(parameter.getNameIdentifier(), elementFactory.createIdentifier(newName));
}
}
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement resolve = expression.resolve();
if (resolve instanceof PsiParameter) {
final String newName = names.get(resolve);
if (newName != null) {
replacements.put(expression, elementFactory.createExpressionFromText(newName, expression));
}
}
}
});
for (PsiElement psiElement : replacements.keySet()) {
psiElement.replace(replacements.get(psiElement));
}
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
ChangeContextUtil.decodeContextInfo(lambdaExpression, null, null);
@@ -254,18 +293,17 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
interfaceType) != null;
}
private static String composeLambdaText(PsiMethod method, final PsiElement lambdaContext, final boolean appendType) {
private static String composeLambdaText(PsiMethod method, final boolean appendType) {
final StringBuilder buf = new StringBuilder();
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != 1 || appendType) {
buf.append("(");
}
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(lambdaContext.getProject());
buf.append(StringUtil.join(parameters,
new Function<PsiParameter, String>() {
@Override
public String fun(PsiParameter parameter) {
return composeParameter(parameter, appendType, codeStyleManager, lambdaContext);
return composeParameter(parameter, appendType);
}
}, ","));
if (parameters.length != 1 || appendType) {
@@ -276,9 +314,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
}
private static String composeParameter(PsiParameter parameter,
boolean appendType,
JavaCodeStyleManager codeStyleManager,
PsiElement lambdaContext) {
boolean appendType) {
final String parameterType;
if (appendType) {
final PsiTypeElement typeElement = parameter.getTypeElement();
@@ -291,7 +327,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
if (parameterName == null) {
parameterName = "";
}
return parameterType + codeStyleManager.suggestUniqueVariableName(parameterName, lambdaContext, true);
return parameterType + parameterName;
}
}
}
@@ -176,12 +176,18 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
}
private static PsiType handleBoundComposition(PsiWildcardType wildcardType, PsiWildcardType bound) {
final PsiType newBoundBound = bound.getBound();
if (bound.isExtends() == wildcardType.isExtends()) {
final PsiType newBoundBound = bound.getBound();
if (newBoundBound != null) {
return rebound(wildcardType, newBoundBound);
}
}
if (newBoundBound != null) {
return wildcardType.isExtends() ? PsiWildcardType.createExtends(wildcardType.getManager(), newBoundBound)
: PsiWildcardType.createSuper(wildcardType.getManager(), newBoundBound);
}
return PsiWildcardType.createUnbounded(wildcardType.getManager());
}
@@ -151,9 +151,8 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiClass interfaceClass = classResolveResult.getElement();
LOG.assertTrue(interfaceClass != null);
if (PsiPolyExpressionUtil.mentionsTypeParameters(interfaceMethodReturnType,
ContainerUtil.newHashSet(interfaceClass.getTypeParameters()))) {
if (PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType,
ContainerUtil.newHashSet(method.getTypeParameters()))) {
LOG.assertTrue(interfaceMethodReturnType != null);
constraints.add(new TypeCompatibilityConstraint(referencedMethodReturnType, interfaceMethodReturnType));
return true;
@@ -1,5 +1,5 @@
public class LambdaTest {
Op lambda_fib = (n) -> (n < 2) ? 1 : lambda_fib.op(n - 1) + lambda_fib.op(n - 2);
Op lambda_fib = (n) -> (n < 2) ? 1 : <error descr="Illegal forward reference">lambda_fib</error>.op(n - 1) + <error descr="Illegal forward reference">lambda_fib</error>.op(n - 2);
{
Op lambda_fib = (n) -> (n < 2) ? 1 : <error descr="Variable 'lambda_fib' might not have been initialized">lambda_fib</error>.op(n - 1) + lambda_fib.op(n - 2);
@@ -5,14 +5,14 @@ class Test {
static void test() {
Integer next = map(String::length).iterator().next();
<error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.Integer'">Integer next1 = map(Test::length).iterator().next();</error>
Integer next1 = map(Test::length).iterator().next();//error with int!!!
}
public static <T> T length(T s) {
return null;
}
public static <T> int length(String s) {
public static <T> /*int*/Integer length(String s) {
return 0;
}
}
@@ -0,0 +1,18 @@
public class Test {
{
addListener(this::editPropertyChanged);
}
void addListener(ChangeListener<? super Boolean> changeListener){}
public void editPropertyChanged(Value<? extends Boolean> property) {}
interface ChangeListener <T> {
void changed(Value<? extends T> value);
}
class Value<K> {}
}
@@ -0,0 +1,21 @@
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Test {
public <T2> void validate(Stream<ConstraintViolation<T2>> stream) {
// ...
Set<Violation> violations = stream.map(this::convertToResult).collect(Collectors.toSet());
// ...
}
private <T1> Violation convertToResult(ConstraintViolation<T1> violation) {
// ...
return new Violation();
}
class Violation {}
class ConstraintViolation<T> {
}
}
@@ -2,6 +2,6 @@
class Test {
{
String o = "";
Comparable<String> c = o1 -> 0;
Comparable<String> c = o1 -> o1.length();
}
}
@@ -0,0 +1,21 @@
// "Replace with lambda" "true"
public class MyNameConflict {
{
int x = 0;
Comparable<E> c = x1 -> {
switch (x1) {
case EE:
break;
}
return x1.hashCode();
};
}
static enum E {
EE;
}
}
@@ -5,7 +5,7 @@ class Test {
Comparable<String> c = new Compa<caret>rable<String>() {
@Override
public int compareTo(String o) {
return 0;
return o.length();
}
};
}
@@ -0,0 +1,24 @@
// "Replace with lambda" "true"
public class MyNameConflict {
{
int x = 0;
Comparable<E> c = new Compara<caret>ble<E>() {
@Override
public int compareTo(E x) {
switch (x) {
case EE:
break;
}
return x.hashCode();
}
};
}
static enum E {
EE;
}
}
@@ -0,0 +1,11 @@
// "Replace with lambda" "false"
class MyTest {
final Runnable anonymRunnable = new Run<caret>nable() {
@Override
public void run() {
System.out.println(o);
}
};
Object o;
}
@@ -137,6 +137,18 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void _testLambdaExercise() throws Exception {
doTest();
}
public void testIDEA118437() throws Exception {
doTest();
}
public void testIDEA113297() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}
@@ -16,6 +16,7 @@
package com.intellij.psi.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.progress.EmptyProgressIndicator;
@@ -192,18 +193,14 @@ public abstract class DocumentCommitProcessor {
FileElement myTreeElementBeingReparsedSoItWontBeCollected) {
if (myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() != document.getTextLength()) {
final String documentText = document.getText();
if (ApplicationManager.getApplication().isInternal()) {
String fileText = file.getText();
LOG.error("commitDocument left PSI inconsistent; file len=" + myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() +
"; doc len=" + document.getTextLength() +
"; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText) +
";\n file psi text=" + fileText +
";\n doc text=" + documentText +
";\n old psi file text=" + oldPsiText);
}
else {
LOG.error("commitDocument left PSI inconsistent: " + file);
}
String fileText = file.getText();
LOG.error("commitDocument left PSI inconsistent: " + file +
"; file len=" + myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() +
"; doc len=" + document.getTextLength() +
"; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText),
new Attachment("file psi text", fileText),
new Attachment("old text", documentText),
new Attachment("old psi file text", oldPsiText));
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
try {
@@ -35,7 +35,7 @@ public class ImportFromGradleControl
extends AbstractImportFromExternalSystemControl<GradleProjectSettings, GradleSettingsListener, GradleSettings>
{
public ImportFromGradleControl() {
super(GradleConstants.SYSTEM_ID, new GradleSettings(ProjectManager.getInstance().getDefaultProject()), getInitialProjectSettings());
super(GradleConstants.SYSTEM_ID, new GradleSettings(ProjectManager.getInstance().getDefaultProject()), getInitialProjectSettings(), true);
}
@NotNull