summaryrefslogtreecommitdiff
path: root/java/java-impl/src/com/intellij/codeInspection
diff options
context:
space:
mode:
Diffstat (limited to 'java/java-impl/src/com/intellij/codeInspection')
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java37
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java6
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/ReplaceWithTernaryOperatorFix.java10
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java63
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java34
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java55
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java65
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/Nullness.java23
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java25
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java23
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java26
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java21
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspection.java37
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java1
18 files changed, 290 insertions, 146 deletions
diff --git a/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java b/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java
index 75116480fdf0..1c54bff2716e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java
@@ -205,34 +205,42 @@ public class LambdaCanBeMethReferenceInspection extends BaseJavaLocalInspectionT
final String methodReferenceName = methodExpression.getReferenceName();
if (qualifierExpression != null) {
boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, psiMethod);
- methodRefText = (isReceiverType ? containingClass.getQualifiedName() : qualifierExpression.getText()) + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodReferenceName;
+ methodRefText = (isReceiverType ? getClassReferenceName(containingClass) : qualifierExpression.getText()) + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodReferenceName;
}
else {
methodRefText =
- (psiMethod.hasModifierProperty(PsiModifier.STATIC) ? containingClass.getQualifiedName() : "this") + "::" + methodReferenceName;
+ (psiMethod.hasModifierProperty(PsiModifier.STATIC) ? getClassReferenceName(containingClass) : "this") + "::" + methodReferenceName;
}
}
else if (element instanceof PsiNewExpression) {
final PsiMethod constructor = ((PsiNewExpression)element).resolveConstructor();
+ PsiClass containingClass = null;
if (constructor != null) {
- final PsiClass containingClass = constructor.getContainingClass();
+ containingClass = constructor.getContainingClass();
LOG.assertTrue(containingClass != null);
- methodRefText = containingClass.getQualifiedName() + "::new";
}
else {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)element).getClassOrAnonymousClassReference();
if (classReference != null) {
final JavaResolveResult resolve = classReference.advancedResolve(false);
- final PsiElement containingClass = resolve.getElement();
- if (containingClass instanceof PsiClass) {
- methodRefText = ((PsiClass)containingClass).getQualifiedName() + "::new";
+ final PsiElement resolveElement = resolve.getElement();
+ if (resolveElement instanceof PsiClass) {
+ containingClass = (PsiClass)resolveElement;
}
}
}
+ if (containingClass != null) {
+ methodRefText = getClassReferenceName(containingClass) + "::new";
+ }
}
return methodRefText;
}
+ private static String getClassReferenceName(PsiClass containingClass) {
+ final String qualifiedName = containingClass.getQualifiedName();
+ return qualifiedName != null ? qualifiedName : containingClass.getName();
+ }
+
private static class ReplaceWithMethodRefFix implements LocalQuickFix {
@NotNull
@Override
@@ -251,12 +259,21 @@ public class LambdaCanBeMethReferenceInspection extends BaseJavaLocalInspectionT
final PsiElement element = descriptor.getPsiElement();
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
if (lambdaExpression == null) return;
- final String methodRefText = createMethodReferenceText(element, lambdaExpression.getFunctionalInterfaceType());
+ final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
+ final String methodRefText = createMethodReferenceText(element, functionalInterfaceType);
if (methodRefText != null) {
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiExpression psiExpression =
- JavaPsiFacade.getElementFactory(project).createExpressionFromText(methodRefText, lambdaExpression);
- JavaCodeStyleManager.getInstance(project).shortenClassReferences(lambdaExpression.replace(psiExpression));
+ factory.createExpressionFromText(methodRefText, lambdaExpression);
+ PsiElement replace = lambdaExpression.replace(psiExpression);
+ if (((PsiMethodReferenceExpression)replace).getFunctionalInterfaceType() == null) { //ambiguity
+ final PsiTypeCastExpression cast = (PsiTypeCastExpression)factory.createExpressionFromText("(A)a", replace);
+ cast.getCastType().replace(factory.createTypeElement(functionalInterfaceType));
+ cast.getOperand().replace(replace);
+ replace = replace.replace(cast);
+ }
+ JavaCodeStyleManager.getInstance(project).shortenClassReferences(replace);
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
index 3ee49d07d7b9..ee5e883e3a2d 100644
--- a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
@@ -107,10 +107,12 @@ public class RedundantSuppressInspection extends GlobalInspectionTool{
@Nullable
private CommonProblemDescriptor[] checkElement(RefClass refEntity, InspectionManager manager, final Project project) {
- return checkElement(refEntity.getElement(), manager, project);
+ final PsiClass psiClass = refEntity.getElement();
+ if (psiClass == null) return null;
+ return checkElement(psiClass, manager, project);
}
- public CommonProblemDescriptor[] checkElement(final PsiElement psiElement, InspectionManager manager, Project project) {
+ public CommonProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, InspectionManager manager, Project project) {
final Map<PsiElement, Collection<String>> suppressedScopes = new THashMap<PsiElement, Collection<String>>();
psiElement.accept(new JavaRecursiveElementWalkingVisitor() {
@Override public void visitModifierList(PsiModifierList list) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/ReplaceWithTernaryOperatorFix.java b/java/java-impl/src/com/intellij/codeInspection/ReplaceWithTernaryOperatorFix.java
index d08ba72cc81f..cf08dacf7045 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ReplaceWithTernaryOperatorFix.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ReplaceWithTernaryOperatorFix.java
@@ -49,7 +49,15 @@ public class ReplaceWithTernaryOperatorFix implements LocalQuickFix {
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- final PsiElement element = descriptor.getPsiElement();
+ PsiElement element = descriptor.getPsiElement();
+ while (true) {
+ PsiElement parent = element.getParent();
+ if (parent instanceof PsiReferenceExpression || parent instanceof PsiMethodCallExpression) {
+ element = parent;
+ } else {
+ break;
+ }
+ }
if (!(element instanceof PsiExpression)) {
return;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
index 992969dda54e..e3170217680f 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
@@ -21,7 +21,9 @@ import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -31,7 +33,14 @@ import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_ERROR;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_THROWABLE;
class ControlFlowAnalyzer extends JavaElementVisitor {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer");
@@ -45,7 +54,8 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
private int myPassNumber;
private Set<DfaVariableValue> myFields;
private Stack<CatchDescriptor> myCatchStack;
- private PsiType myRuntimeException;
+ private DfaValue myRuntimeException;
+ private DfaValue myError;
ControlFlowAnalyzer(final DfaValueFactory valueFactory) {
myFactory = valueFactory;
@@ -54,7 +64,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
public ControlFlow buildControlFlow(PsiElement codeFragment) {
if (codeFragment == null) return null;
- myRuntimeException = PsiType.getJavaLangRuntimeException(codeFragment.getManager(), codeFragment.getResolveScope());
+ PsiManager manager = codeFragment.getManager();
+ GlobalSearchScope scope = codeFragment.getResolveScope();
+ myRuntimeException = myFactory.getNotNullFactory().create(PsiType.getJavaLangRuntimeException(manager, scope));
+ myError = myFactory.getNotNullFactory().create(PsiType.getJavaLangError(manager, scope));
myFields = new HashSet<DfaVariableValue>();
myCatchStack = new Stack<CatchDescriptor>();
myPassNumber = 1;
@@ -638,10 +651,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
continue;
}
- PsiType type = cd.getType();
- if (type instanceof PsiDisjunctionType) {
- type = ((PsiDisjunctionType)type).getLeastUpperBound();
- }
+ PsiType type = cd.getLubType();
if (type instanceof PsiClassType && ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)type)) {
addConditionalRuntimeThrow(cd, true);
break;
@@ -655,8 +665,22 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
addInstruction(branch);
addInstruction(new EmptyStackInstruction());
if (forCatch) {
- addInstruction(new PushInstruction(myFactory.getNotNullFactory().create(myRuntimeException), null));
- addGotoCatch(cd);
+ PsiType type = cd.getLubType();
+ boolean isRuntime = InheritanceUtil.isInheritor(type, JAVA_LANG_RUNTIME_EXCEPTION) || ExceptionUtil.isGeneralExceptionType(type);
+ boolean isError = InheritanceUtil.isInheritor(type, JAVA_LANG_ERROR) || type.equalsToText(JAVA_LANG_THROWABLE);
+ if (isRuntime != isError) {
+ addInstruction(new PushInstruction(isRuntime ? myRuntimeException : myError, null));
+ addGotoCatch(cd);
+ } else {
+ pushUnknown();
+ final ConditionalGotoInstruction branch2 = new ConditionalGotoInstruction(-1, false, null);
+ addInstruction(branch2);
+ addInstruction(new PushInstruction(myError, null));
+ addGotoCatch(cd);
+ branch2.setOffset(myCurrentFlow.getInstructionCount());
+ addInstruction(new PushInstruction(myRuntimeException, null));
+ addGotoCatch(cd);
+ }
}
else {
addInstruction(new GosubInstruction(cd.getJumpOffset(this)));
@@ -755,6 +779,14 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
return myType;
}
+ PsiType getLubType() {
+ PsiType type = myType;
+ if (type instanceof PsiDisjunctionType) {
+ return ((PsiDisjunctionType)type).getLeastUpperBound();
+ }
+ return type;
+ }
+
public boolean isFinally() {
return myIsFinally;
}
@@ -1222,7 +1254,11 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
}
}
- addInstruction(new MethodCallInstruction(expression, createChainedVariableValue(expression)));
+ MethodCallInstruction callInstruction = new MethodCallInstruction(expression, createChainedVariableValue(expression));
+ if (!DfaValueFactory.isEffectivelyUnqualified(methodExpression)) {
+ callInstruction.setShouldFlushFields(false);
+ }
+ addInstruction(callInstruction);
if (!myCatchStack.isEmpty()) {
addMethodThrows(expression.resolveMethod());
@@ -1560,7 +1596,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null, isCall);
}
- if (DfaVariableState.isFinalField(var)) {
+ if (DfaUtil.isFinalField(var) || DfaUtil.isPlainMutableField(var)) {
DfaVariableValue qualifierValue = createChainedVariableValue(qualifier);
if (qualifierValue != null) {
return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, qualifierValue, isCall || qualifierValue.isViaMethods());
@@ -1576,7 +1612,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
return (PsiVariable)target;
}
if (target instanceof PsiMethod) {
- return PropertyUtils.getSimplyReturnedField((PsiMethod)target, PropertyUtils.getSingleReturnValue((PsiMethod)target));
+ PsiMethod method = (PsiMethod)target;
+ if (PropertyUtils.isSimpleGetter(method)) {
+ return PropertyUtils.getSimplyReturnedField(method, PropertyUtils.getSingleReturnValue(method));
+ }
}
return null;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
index e8b74efd73d0..87e0d2dad351 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
@@ -28,7 +28,9 @@ import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.*;
+import com.intellij.psi.JavaTokenType;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
@@ -77,15 +79,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
newState.myEqClasses.add(aClass != null ? new SortedIntSet(aClass.toNativeArray()) : null);
}
- try {
- for (Object o : myVariableStates.keySet()) {
- DfaVariableValue dfaVariableValue = (DfaVariableValue)o;
- DfaVariableState clone = (DfaVariableState)myVariableStates.get(dfaVariableValue).clone();
- newState.myVariableStates.put(dfaVariableValue, clone);
- }
- }
- catch (CloneNotSupportedException e) {
- LOG.error(e);
+ for (DfaVariableValue dfaVariableValue : myVariableStates.keySet()) {
+ newState.myVariableStates.put(dfaVariableValue, myVariableStates.get(dfaVariableValue).clone());
}
return newState;
}
@@ -280,13 +275,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
applyCondition(dfaEqual);
if (value instanceof DfaVariableValue) {
- try {
- DfaVariableState newState = (DfaVariableState)getVariableState((DfaVariableValue)value).clone();
- myVariableStates.put(var, newState);
- }
- catch (CloneNotSupportedException e) {
- LOG.error(e);
- }
+ myVariableStates.put(var, getVariableState((DfaVariableValue)value).clone());
}
}
@@ -782,18 +771,15 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
public void flushFields(DataFlowRunner runner) {
for (DfaVariableValue field : runner.getFields()) {
if (myVariableStates.containsKey(field) || getEqClassIndex(field) >= 0) {
- flushVariable(field);
- getVariableState(field).setNullable(false);
+ if (!DfaUtil.isFinalField(field.getPsiVariable())) {
+ flushWithDependencies(field);
+ getVariableState(field).setNullable(false);
+ }
}
}
}
public void flushVariable(@NotNull DfaVariableValue variable) {
- PsiVariable psiVariable = variable.getPsiVariable();
- if (DfaVariableState.isFinalField(psiVariable)) {
- return;
- }
-
flushWithDependencies(variable);
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
index 065464ff47b5..69c7b05f8e2b 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
+import com.intellij.codeInspection.nullable.NullableStuffInspection;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.openapi.util.Ref;
@@ -85,17 +86,17 @@ public class DfaUtil {
return expressions == null ? Collections.<PsiExpression>emptyList() : expressions;
}
- @Nullable
- static Boolean getElementNullability(@Nullable PsiType resultType, @Nullable PsiModifierListOwner owner) {
+ @NotNull
+ public static Nullness getElementNullability(@Nullable PsiType resultType, @Nullable PsiModifierListOwner owner) {
if (owner == null) {
- return null;
+ return Nullness.UNKNOWN;
}
if (NullableNotNullManager.isNullable(owner)) {
- return Boolean.TRUE;
+ return Nullness.NULLABLE;
}
if (NullableNotNullManager.isNotNull(owner)) {
- return Boolean.FALSE;
+ return Nullness.NOT_NULL;
}
if (resultType != null) {
@@ -103,19 +104,51 @@ public class DfaUtil {
for (PsiAnnotation annotation : resultType.getAnnotations()) {
String qualifiedName = annotation.getQualifiedName();
if (nnn.getNullables().contains(qualifiedName)) {
- return Boolean.TRUE;
+ return Nullness.NULLABLE;
}
if (nnn.getNotNulls().contains(qualifiedName)) {
- return Boolean.FALSE;
+ return Nullness.NOT_NULL;
}
}
}
- return null;
+ return Nullness.UNKNOWN;
+ }
+
+ public static boolean isNullableInitialized(PsiVariable var, boolean nullable) {
+ if (!isFinalField(var)) {
+ return false;
+ }
+
+ List<PsiExpression> initializers = NullableStuffInspection.findAllConstructorInitializers((PsiField)var);
+ if (initializers.isEmpty()) {
+ return false;
+ }
+
+ for (PsiExpression expression : initializers) {
+ if (!(expression instanceof PsiReferenceExpression)) {
+ return false;
+ }
+ PsiElement target = ((PsiReferenceExpression)expression).resolve();
+ if (!(target instanceof PsiParameter)) {
+ return false;
+ }
+ if (nullable && NullableNotNullManager.isNullable((PsiParameter)target)) {
+ return true;
+ }
+ if (!nullable && !NullableNotNullManager.isNotNull((PsiParameter)target)) {
+ return false;
+ }
+ }
+ return !nullable;
+ }
+
+ public static boolean isPlainMutableField(PsiVariable var) {
+ return !var.hasModifierProperty(PsiModifier.FINAL) && !var.hasModifierProperty(PsiModifier.TRANSIENT) && !var.hasModifierProperty(PsiModifier.VOLATILE) && var instanceof PsiField;
}
- public static enum Nullness {
- NOT_NULL,NULL,UNKNOWN
+ public static boolean isFinalField(PsiVariable var) {
+ return var.hasModifierProperty(PsiModifier.FINAL) && !var.hasModifierProperty(PsiModifier.TRANSIENT) && var instanceof PsiField;
}
@NotNull
@@ -131,7 +164,7 @@ public class DfaUtil {
if (result != RunnerResult.OK) {
return Nullness.UNKNOWN;
}
- if (visitor.myNulls.contains(variable) && !visitor.myNotNulls.contains(variable)) return Nullness.NULL;
+ if (visitor.myNulls.contains(variable) && !visitor.myNotNulls.contains(variable)) return Nullness.NULLABLE;
if (visitor.myNotNulls.contains(variable) && !visitor.myNulls.contains(variable)) return Nullness.NOT_NULL;
return Nullness.UNKNOWN;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java
index 02e841c89132..7c86f7f4e27b 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java
@@ -24,11 +24,9 @@
*/
package com.intellij.codeInspection.dataFlow;
-import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInspection.dataFlow.value.DfaTypeValue;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
-import com.intellij.codeInspection.nullable.NullableStuffInspection;
import com.intellij.psi.*;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
@@ -37,65 +35,28 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
import java.util.Set;
public class DfaVariableState implements Cloneable {
private final Set<DfaTypeValue> myInstanceofValues;
private final Set<DfaTypeValue> myNotInstanceofValues;
- private boolean myNullable = false;
- private final boolean myVariableIsDeclaredNotNull;
+ private Nullness myNullability;
public DfaVariableState(@NotNull DfaVariableValue dfaVar) {
myInstanceofValues = new HashSet<DfaTypeValue>();
myNotInstanceofValues = new HashSet<DfaTypeValue>();
- PsiVariable var = dfaVar.getPsiVariable();
- Boolean nullability = DfaUtil.getElementNullability(dfaVar.getVariableType(), var);
- myNullable = nullability == Boolean.TRUE || var != null && isNullableInitialized(var, true);
- myVariableIsDeclaredNotNull = nullability == Boolean.FALSE || var != null && isNullableInitialized(var, false);
+
+ myNullability = dfaVar.getInherentNullability();
}
protected DfaVariableState(final DfaVariableState toClone) {
myInstanceofValues = new THashSet<DfaTypeValue>(toClone.myInstanceofValues);
myNotInstanceofValues = new THashSet<DfaTypeValue>(toClone.myNotInstanceofValues);
- myNullable = toClone.myNullable;
- myVariableIsDeclaredNotNull = toClone.myVariableIsDeclaredNotNull;
- }
-
- private static boolean isNullableInitialized(PsiVariable var, boolean nullable) {
- if (!isFinalField(var)) {
- return false;
- }
-
- List<PsiExpression> initializers = NullableStuffInspection.findAllConstructorInitializers((PsiField)var);
- if (initializers.isEmpty()) {
- return false;
- }
-
- for (PsiExpression expression : initializers) {
- if (!(expression instanceof PsiReferenceExpression)) {
- return false;
- }
- PsiElement target = ((PsiReferenceExpression)expression).resolve();
- if (!(target instanceof PsiParameter)) {
- return false;
- }
- if (nullable && NullableNotNullManager.isNullable((PsiParameter)target)) {
- return true;
- }
- if (!nullable && !NullableNotNullManager.isNotNull((PsiParameter)target)) {
- return false;
- }
- }
- return !nullable;
- }
-
- public static boolean isFinalField(PsiVariable var) {
- return var.hasModifierProperty(PsiModifier.FINAL) && !var.hasModifierProperty(PsiModifier.TRANSIENT) && var instanceof PsiField;
+ myNullability = toClone.myNullability;
}
public boolean isNullable() {
- return myNullable;
+ return myNullability == Nullness.NULLABLE;
}
private boolean checkInstanceofValue(DfaTypeValue dfaType) {
@@ -113,7 +74,9 @@ public class DfaVariableState implements Cloneable {
}
public boolean setInstanceofValue(DfaTypeValue dfaType) {
- myNullable |= dfaType.isNullable();
+ if (dfaType.isNullable()) {
+ myNullability = Nullness.NULLABLE;
+ }
if (dfaType.getType() instanceof PsiPrimitiveType) return true;
@@ -146,10 +109,10 @@ public class DfaVariableState implements Cloneable {
DfaVariableState aState = (DfaVariableState) obj;
return myInstanceofValues.equals(aState.myInstanceofValues) &&
myNotInstanceofValues.equals(aState.myNotInstanceofValues) &&
- myNullable == aState.myNullable;
+ myNullability == aState.myNullability;
}
- protected Object clone() throws CloneNotSupportedException {
+ protected DfaVariableState clone() {
return new DfaVariableState(this);
}
@@ -169,16 +132,18 @@ public class DfaVariableState implements Cloneable {
buf.append("{").append(dfaTypeValue).append("}");
if (iterator.hasNext()) buf.append(", ");
}
- buf.append(", nullable=").append(myNullable);
+ buf.append(", nullable=").append(myNullability);
return buf.toString();
}
public boolean isNotNull() {
- return myVariableIsDeclaredNotNull;
+ return myNullability == Nullness.NOT_NULL;
}
public void setNullable(final boolean nullable) {
- myNullable = nullable;
+ if (myNullability != Nullness.NOT_NULL) {
+ myNullability = nullable ? Nullness.NULLABLE : Nullness.UNKNOWN;
+ }
}
public void setValue(DfaValue value) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/Nullness.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/Nullness.java
new file mode 100644
index 000000000000..3dd099b0c1d3
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/Nullness.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2013 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.
+ */
+package com.intellij.codeInspection.dataFlow;
+
+/**
+* @author cdr
+*/
+public enum Nullness {
+ NOT_NULL, NULLABLE,UNKNOWN
+}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
index a216be6f3cb0..54df852bfbab 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
@@ -40,26 +40,26 @@ public class StandardInstructionVisitor extends InstructionVisitor {
private final Set<BinopInstruction> myCanBeNullInInstanceof = new THashSet<BinopInstruction>();
private final Set<PsiElement> myNotToReportReachability = new THashSet<PsiElement>();
private final Set<InstanceofInstruction> myUsefulInstanceofs = new THashSet<InstanceofInstruction>();
- private final FactoryMap<MethodCallInstruction, Map<PsiExpression, Boolean>> myParametersNullability = new FactoryMap<MethodCallInstruction, Map<PsiExpression, Boolean>>() {
+ private final FactoryMap<MethodCallInstruction, Map<PsiExpression, Nullness>> myParametersNullability = new FactoryMap<MethodCallInstruction, Map<PsiExpression, Nullness>>() {
@Nullable
@Override
- protected Map<PsiExpression, Boolean> create(MethodCallInstruction key) {
+ protected Map<PsiExpression, Nullness> create(MethodCallInstruction key) {
return calcParameterNullability(key.getCallExpression());
}
};
- private final FactoryMap<MethodCallInstruction, Boolean> myReturnTypeNullability = new FactoryMap<MethodCallInstruction, Boolean>() {
+ private final FactoryMap<MethodCallInstruction, Nullness> myReturnTypeNullability = new FactoryMap<MethodCallInstruction, Nullness>() {
@Override
- protected Boolean create(MethodCallInstruction key) {
+ protected Nullness create(MethodCallInstruction key) {
final PsiCallExpression callExpression = key.getCallExpression();
if (callExpression instanceof PsiNewExpression) {
- return Boolean.FALSE;
+ return Nullness.NOT_NULL;
}
return callExpression != null ? DfaUtil.getElementNullability(key.getResultType(), callExpression.resolveMethod()) : null;
}
};
- private static Map<PsiExpression, Boolean> calcParameterNullability(@Nullable PsiCallExpression callExpression) {
+ private static Map<PsiExpression, Nullness> calcParameterNullability(@Nullable PsiCallExpression callExpression) {
PsiExpressionList argumentList = callExpression == null ? null : callExpression.getArgumentList();
if (argumentList != null) {
JavaResolveResult result = callExpression.resolveMethodGenerics();
@@ -72,7 +72,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
boolean varArg = isVarArgCall(method, substitutor, args, parameters);
int checkedCount = Math.min(args.length, parameters.length) - (varArg ? 1 : 0);
- Map<PsiExpression, Boolean> map = ContainerUtil.newHashMap();
+ Map<PsiExpression, Nullness> map = ContainerUtil.newHashMap();
for (int i = 0; i < checkedCount; i++) {
map.put(args[i], DfaUtil.getElementNullability(substitutor.substitute(parameters[i].getType()), parameters[i]));
}
@@ -112,7 +112,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
if (dfaDest instanceof DfaVariableValue) {
DfaVariableValue var = (DfaVariableValue) dfaDest;
final PsiVariable psiVariable = var.getPsiVariable();
- if (DfaUtil.getElementNullability(var.getVariableType(), psiVariable) == Boolean.FALSE) {
+ if (DfaUtil.getElementNullability(var.getVariableType(), psiVariable) == Nullness.NOT_NULL) {
if (!memState.applyNotNull(dfaSource)) {
onAssigningToNotNullableVariable(instruction);
}
@@ -183,12 +183,12 @@ public class StandardInstructionVisitor extends InstructionVisitor {
@Override
public DfaInstructionState[] visitMethodCall(MethodCallInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
final PsiExpression[] args = instruction.getArgs();
- Map<PsiExpression, Boolean> map = myParametersNullability.get(instruction);
+ Map<PsiExpression, Nullness> map = myParametersNullability.get(instruction);
final DfaNotNullValue.Factory factory = runner.getFactory().getNotNullFactory();
for (int i = 0; i < args.length; i++) {
final DfaValue arg = memState.pop();
PsiExpression expr = args[(args.length - i - 1)];
- if (map.get(expr) == Boolean.FALSE) {
+ if (map.get(expr) == Nullness.NOT_NULL) {
if (!memState.applyNotNull(arg)) {
onPassingNullParameter(expr);
if (arg instanceof DfaVariableValue) {
@@ -196,7 +196,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
}
}
}
- else if (map.containsKey(expr) && map.get(expr) == null && !memState.checkNotNullable(arg)) {
+ else if (map.get(expr) == Nullness.UNKNOWN && !memState.checkNotNullable(arg)) {
onPassingNullParameterToNonAnnotated(runner, expr);
}
}
@@ -230,8 +230,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
final PsiType type = instruction.getResultType();
final MethodCallInstruction.MethodType methodType = instruction.getMethodType();
if (type != null && (type instanceof PsiClassType || type.getArrayDimensions() > 0)) {
- @Nullable final Boolean nullability = myReturnTypeNullability.get(instruction);
- return factory.createTypeValueWithNullability(type, nullability);
+ return factory.createTypeValueWithNullability(type, myReturnTypeNullability.get(instruction));
}
if (methodType == MethodCallInstruction.MethodType.UNBOXING) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java
index 8ae655d475b9..d715f7637c9d 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java
@@ -67,7 +67,7 @@ public class ValuableDataFlowRunner extends AnnotationsAwareDataFlowRunner {
return myValue;
}
- protected Object clone() throws CloneNotSupportedException {
+ protected ValuableDfaVariableState clone() {
return new ValuableDfaVariableState(this);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java
index 22f98623447d..5f65a86caeed 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java
@@ -72,6 +72,10 @@ public class MethodCallInstruction extends Instruction {
}
}
+ public void setShouldFlushFields(boolean shouldFlushFields) {
+ myShouldFlushFields = shouldFlushFields;
+ }
+
@Nullable
public PsiType getResultType() {
return myType;
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
index 83c9f5efaafb..d68679796fc4 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
@@ -24,9 +24,11 @@
*/
package com.intellij.codeInspection.dataFlow.value;
+import com.intellij.codeInspection.dataFlow.Nullness;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
+import com.intellij.psi.util.PsiTreeUtil;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,8 +51,8 @@ public class DfaValueFactory {
myRelationFactory = new DfaRelationValue.Factory(this);
}
- public DfaValue createTypeValueWithNullability(@Nullable PsiType type, @Nullable Boolean nullability) {
- return nullability == Boolean.FALSE ? getNotNullFactory().create(type) : getTypeFactory().create(type, nullability == Boolean.TRUE);
+ public DfaValue createTypeValueWithNullability(@Nullable PsiType type, Nullness nullability) {
+ return nullability == Nullness.NOT_NULL ? getNotNullFactory().create(type) : getTypeFactory().create(type, nullability == Nullness.NULLABLE);
}
int createID() {
@@ -133,7 +135,7 @@ public class DfaValueFactory {
}
}
- if (isEffectivelyUnqualified(referenceExpression)) {
+ if (!variable.hasModifierProperty(PsiModifier.VOLATILE) && isEffectivelyUnqualified(referenceExpression)) {
return getVarFactory().createVariableValue(variable, referenceExpression.getType(), false, null, false);
}
@@ -152,9 +154,20 @@ public class DfaValueFactory {
return null;
}
- private static boolean isEffectivelyUnqualified(PsiReferenceExpression refExpression) {
+ public static boolean isEffectivelyUnqualified(PsiReferenceExpression refExpression) {
PsiExpression qualifier = refExpression.getQualifierExpression();
- return qualifier == null || qualifier instanceof PsiThisExpression;
+ if (qualifier == null) {
+ return true;
+ }
+ if (qualifier instanceof PsiThisExpression){
+ final PsiJavaCodeReferenceElement thisQualifier = ((PsiThisExpression)qualifier).getQualifier();
+ if (thisQualifier == null) return true;
+ final PsiClass innerMostClass = PsiTreeUtil.getParentOfType(refExpression, PsiClass.class);
+ if (innerMostClass == thisQualifier.resolve()) {
+ return true;
+ }
+ }
+ return false;
}
private final DfaVariableValue.Factory myVarFactory;
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
index 1c0434dd6ddc..f56fcd8290eb 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
@@ -24,6 +24,8 @@
*/
package com.intellij.codeInspection.dataFlow.value;
+import com.intellij.codeInspection.dataFlow.DfaUtil;
+import com.intellij.codeInspection.dataFlow.Nullness;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import com.intellij.util.containers.HashMap;
@@ -92,6 +94,7 @@ public class DfaVariableValue extends DfaValue {
@Nullable private DfaVariableValue myQualifier;
private boolean myIsNegated;
private boolean myViaMethods;
+ private Nullness myInherentNullability;
private DfaVariableValue(PsiVariable variable, PsiType varType, boolean isNegated, DfaValueFactory factory, @Nullable DfaVariableValue qualifier, boolean viaMethods) {
super(factory);
@@ -115,7 +118,7 @@ public class DfaVariableValue extends DfaValue {
@Nullable
public PsiType getVariableType() {
- return myVariable == null ? null : myVariable.getType();
+ return myVarType;
}
public boolean isNegated() {
@@ -147,4 +150,25 @@ public class DfaVariableValue extends DfaValue {
public boolean isViaMethods() {
return myViaMethods;
}
+
+ public Nullness getInherentNullability() {
+ if (myInherentNullability != null) {
+ return myInherentNullability;
+ }
+
+ PsiVariable var = getPsiVariable();
+ Nullness nullability = DfaUtil.getElementNullability(getVariableType(), var);
+ if (nullability == Nullness.UNKNOWN && var != null) {
+ if (DfaUtil.isNullableInitialized(var, true)) {
+ nullability = Nullness.NULLABLE;
+ } else if (DfaUtil.isNullableInitialized(var, false)) {
+ nullability = Nullness.NOT_NULL;
+ }
+ }
+
+ myInherentNullability = nullability;
+
+ return nullability;
+ }
+
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java
index 309fefcddba8..6cc4a8cdc709 100644
--- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java
+++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java
@@ -50,15 +50,12 @@ public class FileHeaderChecker {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.defaultFileTemplateUsage.FileHeaderChecker");
static ProblemDescriptor checkFileHeader(@NotNull final PsiFile file, final InspectionManager manager, boolean onTheFly) {
- FileTemplate template = FileTemplateManager.getInstance().getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME);
TIntObjectHashMap<String> offsetToProperty = new TIntObjectHashMap<String>();
- String templateText = template.getText().trim();
- String regex = templateToRegex(templateText, offsetToProperty, file.getProject());
- regex = StringUtil.replace(regex, "with", "(?:with|by)");
- regex = ".*("+regex+").*";
- String fileText = file.getText();
- Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
- Matcher matcher = pattern.matcher(fileText);
+ Pattern pattern = getTemplatePattern(FileTemplateManager.getInstance()
+ .getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME),
+ file.getProject(), offsetToProperty
+ );
+ Matcher matcher = pattern.matcher(file.getText());
if (matcher.matches()) {
final int startOffset = matcher.start(1);
final int endOffset = matcher.end(1);
@@ -83,6 +80,14 @@ public class FileHeaderChecker {
return null;
}
+ public static Pattern getTemplatePattern(FileTemplate template, Project project, TIntObjectHashMap<String> offsetToProperty) {
+ String templateText = template.getText().trim();
+ String regex = templateToRegex(templateText, offsetToProperty, project);
+ regex = StringUtil.replace(regex, "with", "(?:with|by)");
+ regex = ".*("+regex+").*";
+ return Pattern.compile(regex, Pattern.DOTALL);
+ }
+
private static Properties computeProperties(final Matcher matcher, final TIntObjectHashMap<String> offsetToProperty) {
Properties properties = new Properties(FileTemplateManager.getInstance().getDefaultProperties());
int[] offsets = offsetToProperty.keys();
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
index 01fa24239dff..e65e8e4f2db5 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
@@ -135,7 +135,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
else if (entry instanceof LibraryOrderEntry) {
final LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)entry;
final Library library = libraryOrderEntry.getLibrary();
- if (library == null || library.getFiles(OrderRootType.CLASSES).length != library.getUrls(OrderRootType.CLASSES).length) {
+ if (library == null || library.getFiles(OrderRootType.CLASSES).length < library.getUrls(OrderRootType.CLASSES).length) {
System.err.println(InspectionsBundle.message("offline.inspections.library.was.not.resolved",
libraryOrderEntry.getPresentableName(), module.getName()));
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java
index 66444fe29e9e..6923ccceb060 100644
--- a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java
@@ -466,7 +466,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
}
public static List<PsiExpression> findAllConstructorInitializers(PsiField field) {
- final List<PsiExpression> result = ContainerUtil.createEmptyCOWList();
+ final List<PsiExpression> result = ContainerUtil.createLockFreeCopyOnWriteList();
ContainerUtil.addIfNotNull(result, field.getInitializer());
PsiClass containingClass = field.getContainingClass();
diff --git a/java/java-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspection.java b/java/java-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspection.java
index 29ae2b877666..6fd1d33a37f5 100644
--- a/java/java-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspection.java
@@ -21,9 +21,11 @@ import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* User: anna
@@ -120,7 +122,9 @@ public class SillyAssignmentInspection extends BaseJavaLocalInspectionTool {
/**
* @return true if both expressions resolve to the same variable/class or field in the same instance of the class
*/
- private static boolean sameInstanceReferences(PsiReferenceExpression lRef, PsiReferenceExpression rRef, PsiManager manager) {
+ private static boolean sameInstanceReferences(@Nullable PsiJavaCodeReferenceElement lRef, @Nullable PsiJavaCodeReferenceElement rRef, PsiManager manager) {
+ if (lRef == null && rRef == null) return true;
+ if (lRef == null || rRef == null) return false;
PsiElement lResolved = lRef.resolve();
PsiElement rResolved = rRef.resolve();
if (!manager.areElementsEquivalent(lResolved, rResolved)) return false;
@@ -128,15 +132,36 @@ public class SillyAssignmentInspection extends BaseJavaLocalInspectionTool {
final PsiVariable variable = (PsiVariable)lResolved;
if (variable.hasModifierProperty(PsiModifier.STATIC)) return true;
- PsiExpression lQualifier = lRef.getQualifierExpression();
- PsiExpression rQualifier = rRef.getQualifierExpression();
- if (lQualifier instanceof PsiReferenceExpression && rQualifier instanceof PsiReferenceExpression) {
- return sameInstanceReferences((PsiReferenceExpression)lQualifier, (PsiReferenceExpression)rQualifier, manager);
+ final PsiElement lQualifier = lRef.getQualifier();
+ final PsiElement rQualifier = rRef.getQualifier();
+ if (lQualifier instanceof PsiJavaCodeReferenceElement && rQualifier instanceof PsiJavaCodeReferenceElement) {
+ return sameInstanceReferences((PsiJavaCodeReferenceElement)lQualifier, (PsiJavaCodeReferenceElement)rQualifier, manager);
}
+
if (Comparing.equal(lQualifier, rQualifier)) return true;
boolean lThis = lQualifier == null || lQualifier instanceof PsiThisExpression || lQualifier instanceof PsiSuperExpression;
boolean rThis = rQualifier == null || rQualifier instanceof PsiThisExpression || rQualifier instanceof PsiSuperExpression;
- return lThis && rThis;
+ if (lThis && rThis) {
+ final PsiJavaCodeReferenceElement llQualifier = getQualifier(lQualifier);
+ final PsiJavaCodeReferenceElement rrQualifier = getQualifier(rQualifier);
+ return sameInstanceReferences(llQualifier, rrQualifier, manager);
+ }
+ return false;
}
+ private static PsiJavaCodeReferenceElement getQualifier(PsiElement qualifier) {
+ if (qualifier instanceof PsiThisExpression) {
+ final PsiJavaCodeReferenceElement thisQualifier = ((PsiThisExpression)qualifier).getQualifier();
+ if (thisQualifier != null) {
+ final PsiClass innerMostClass = PsiTreeUtil.getParentOfType(thisQualifier, PsiClass.class);
+ if (innerMostClass == thisQualifier.resolve()) {
+ return null;
+ }
+ }
+ return thisQualifier;
+ } else if (qualifier != null) {
+ return ((PsiSuperExpression)qualifier).getQualifier();
+ }
+ return null;
+ }
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
index 833a7d06978b..684d99ca481b 100644
--- a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
@@ -437,6 +437,7 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public Boolean visitClassType(PsiClassType classType) {
PsiClass psiClass = classType.resolve();
if (psiClass instanceof PsiTypeParameter) {
+ if (((PsiTypeParameter)psiClass).getOwner() == method) return Boolean.FALSE;
return substitutor.substitute((PsiTypeParameter)psiClass) == null ? Boolean.TRUE : Boolean.FALSE;
}
PsiType[] parameters = classType.getParameters();