summaryrefslogtreecommitdiff
path: root/plugins/InspectionGadgets/InspectionGadgetsAnalysis
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/InspectionGadgets/InspectionGadgetsAnalysis')
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml7
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties7
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java22
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java23
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java89
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java24
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java4
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java44
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java36
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java122
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionBase.java110
11 files changed, 381 insertions, 107 deletions
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index dddb6e1d3988..4becc9723a65 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -2489,6 +2489,9 @@
<localInspection language="JAVA" suppressId="LockAcquiredButNotSafelyReleased" shortName="SafeLock" bundle="com.siyeh.InspectionGadgetsBundle"
key="safe.lock.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.threading.issues"
enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.threading.SafeLockInspection"/>
+ <localInspection language="JAVA" suppressId="SharedThreadLocalRandom" shortName="SharedThreadLocalRandom" bundle="com.siyeh.InspectionGadgetsBundle"
+ key="shared.thread.local.random.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.threading.issues"
+ enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.threading.SharedThreadLocalRandomInspection"/>
<localInspection language="JAVA" shortName="SignalWithoutCorrespondingAwait" bundle="com.siyeh.InspectionGadgetsBundle"
key="signal.without.corresponding.await.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.threading.issues" enabledByDefault="false" level="WARNING"
@@ -2640,6 +2643,10 @@
bundle="com.siyeh.InspectionGadgetsBundle" key="parameter.hides.member.variable.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.visibility.issues" enabledByDefault="false"
level="WARNING" implementationClass="com.siyeh.ig.visibility.ParameterHidingMemberVariableInspection"/>
+ <localInspection language="JAVA" suppressId="LambdaParameterHidesMemberVariable" shortName="LambdaParameterHidingMemberVariable"
+ bundle="com.siyeh.InspectionGadgetsBundle" key="lambda.parameter.hides.member.variable.display.name"
+ groupBundle="messages.InspectionsBundle" groupKey="group.names.visibility.issues" enabledByDefault="false"
+ level="WARNING" implementationClass="com.siyeh.ig.visibility.LambdaParameterHidingMemberVariableInspection"/>
</extensions>
<application-components>
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index 7f61b374c9a9..013cf2344b2a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1157,7 +1157,7 @@ local.variable.naming.convention.problem.descriptor.long=Local variable name <co
local.variable.naming.convention.problem.descriptor.regex.mismatch=Local variable name <code>#ref</code> doesn''t match regex ''{0}'' #loc
local.variable.naming.convention.ignore.option=Ignore for-loop parameters
local.variable.naming.convention.ignore.catch.option=Ignore 'catch' block parameters
-method.names.differ.only.by.case.problem.descriptor=Method names <code>#ref</code> and ''{0}'' differ only by case #loc
+method.names.differ.only.by.case.problem.descriptor=Method name <code>#ref</code> and method name ''{0}'' differ only by case #loc
parameter.name.differs.from.overridden.parameter.ignore.character.option=Ignore if overridden parameter contains only one character
parameter.name.differs.from.overridden.parameter.ignore.library.option=Ignore if overridden parameter is from a library
parameter.name.differs.from.overridden.parameter.problem.descriptor=Parameter name <code>#ref</code> is different from parameter ''{0}'' overridden #loc
@@ -2066,3 +2066,8 @@ implicit.default.charset.usage.constructor.problem.descriptor=<code>new #ref()</
interface.may.be.annotated.functional.display.name=Interface may be annotated @FunctionalInterface
interface.may.be.annotated.functional.problem.descriptor=Interface <code>#ref</code> may be annotated with @FunctionalInterface
only.report.public.methods.option=Only report 'public' methods
+lambda.parameter.hides.member.variable.display.name=Lambda parameter hides field
+lambda.parameter.hides.member.variable.problem.descriptor=Lambda parameter <code>#ref</code> hides field in class ''{0}'' #loc
+shared.thread.local.random.display.name='ThreadLocalRandom' instance might be shared
+shared.thread.local.random.problem.descriptor='ThreadLocalRandom' instance might be shared between threads
+
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
index 9ef4c14e4a84..31a7987f40f1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2011 Bas Leijdekkers
+ * Copyright 2008-2014 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
@@ -46,8 +45,7 @@ public class ExtractParameterAsLocalVariableFix
}
@Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ public void doFix(Project project, ProblemDescriptor descriptor) {
final PsiReferenceExpression parameterReference =
(PsiReferenceExpression)descriptor.getPsiElement();
final PsiElement target = parameterReference.resolve();
@@ -79,6 +77,10 @@ public class ExtractParameterAsLocalVariableFix
body = forBody;
}
}
+ else if (declarationScope instanceof PsiLambdaExpression) {
+ final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)declarationScope;
+ body = lambdaExpression.getBody();
+ }
else {
return;
}
@@ -125,15 +127,16 @@ public class ExtractParameterAsLocalVariableFix
replaceVariableName(child, firstReference,
variableName, parameterName, buffer);
}
+ if (body instanceof PsiExpression) { // expression lambda
+ buffer.insert(0, "return ");
+ buffer.append(';');
+ }
final String replacementText;
if (newDeclarationCreated) {
replacementText = "{" + buffer + '}';
}
else {
- final PsiType type = parameterReference.getType();
- if (type == null) {
- return;
- }
+ final PsiType type = parameter.getType();
final String className = type.getCanonicalText();
replacementText = '{' + className + ' ' + variableName + " = " +
parameterName + ';' + buffer + '}';
@@ -141,8 +144,7 @@ public class ExtractParameterAsLocalVariableFix
final PsiElementFactory elementFactory =
JavaPsiFacade.getInstance(project).getElementFactory();
final PsiCodeBlock block =
- elementFactory.createCodeBlockFromText(
- replacementText, null);
+ elementFactory.createCodeBlockFromText(replacementText, declarationScope);
body.replace(block);
codeStyleManager.reformat(declarationScope);
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
index 278c07e980c0..3741d260dae6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 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.
@@ -35,7 +35,7 @@ public class ControlFlowUtils {
}
else if (statement instanceof PsiExpressionListStatement || statement instanceof PsiEmptyStatement ||
statement instanceof PsiAssertStatement || statement instanceof PsiDeclarationStatement ||
- statement instanceof PsiSwitchLabelStatement) {
+ statement instanceof PsiSwitchLabelStatement || statement instanceof PsiForeachStatement) {
return true;
}
else if (statement instanceof PsiExpressionStatement) {
@@ -63,9 +63,6 @@ public class ControlFlowUtils {
else if (statement instanceof PsiForStatement) {
return forStatementMayCompleteNormally((PsiForStatement)statement);
}
- else if (statement instanceof PsiForeachStatement) {
- return foreachStatementMayCompleteNormally((PsiForeachStatement)statement);
- }
else if (statement instanceof PsiWhileStatement) {
return whileStatementMayCompleteNormally((PsiWhileStatement)statement);
}
@@ -130,10 +127,6 @@ public class ControlFlowUtils {
return Boolean.TRUE != value;
}
- private static boolean foreachStatementMayCompleteNormally(@NotNull PsiForeachStatement loopStatement) {
- return true;
- }
-
private static boolean switchStatementMayCompleteNormally(@NotNull PsiSwitchStatement switchStatement) {
if (statementIsBreakTarget(switchStatement)) {
return true;
@@ -524,7 +517,7 @@ public class ControlFlowUtils {
}
}
- private static class SystemExitFinder extends JavaRecursiveElementVisitor {
+ private static class SystemExitFinder extends JavaRecursiveElementWalkingVisitor {
private boolean m_found = false;
@@ -564,7 +557,7 @@ public class ControlFlowUtils {
}
}
- private static class ReturnFinder extends JavaRecursiveElementVisitor {
+ private static class ReturnFinder extends JavaRecursiveElementWalkingVisitor {
private boolean m_found = false;
@@ -587,7 +580,7 @@ public class ControlFlowUtils {
}
}
- private static class BreakFinder extends JavaRecursiveElementVisitor {
+ private static class BreakFinder extends JavaRecursiveElementWalkingVisitor {
private boolean m_found = false;
private final PsiStatement m_target;
@@ -637,7 +630,7 @@ public class ControlFlowUtils {
}
}
- private static class ContinueFinder extends JavaRecursiveElementVisitor {
+ private static class ContinueFinder extends JavaRecursiveElementWalkingVisitor {
private boolean m_found = false;
private final PsiStatement m_target;
@@ -687,7 +680,7 @@ public class ControlFlowUtils {
}
}
- private static class MethodCallFinder extends JavaRecursiveElementVisitor {
+ private static class MethodCallFinder extends JavaRecursiveElementWalkingVisitor {
private final String containingClassName;
private final PsiType returnType;
@@ -728,7 +721,7 @@ public class ControlFlowUtils {
}
}
- private static class ContinueToAncestorFinder extends JavaRecursiveElementVisitor {
+ private static class ContinueToAncestorFinder extends JavaRecursiveElementWalkingVisitor {
private final PsiStatement statement;
private boolean found = false;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java
index c14da9f55373..ad5ecc2351f3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java
@@ -153,86 +153,59 @@ public class ExpectedTypeUtils {
}
@Override
- public void visitBinaryExpression(@NotNull PsiBinaryExpression binaryExpression) {
- final PsiExpression rhs = binaryExpression.getROperand();
- if (rhs == null) {
- expectedType = null;
- return;
- }
- final PsiExpression lhs = binaryExpression.getLOperand();
- PsiType lhsType = lhs.getType();
- if (lhsType == null) {
- expectedType = null;
- return;
- }
- PsiType rhsType = rhs.getType();
- if (rhsType == null) {
- expectedType = null;
- return;
+ public void visitPolyadicExpression(@NotNull PsiPolyadicExpression polyadicExpression) {
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ for (PsiExpression operand : operands) {
+ if (operand == null || operand.getType() == null) {
+ expectedType = null;
+ return;
+ }
}
- final IElementType tokenType = binaryExpression.getOperationTokenType();
- final PsiType type = binaryExpression.getType();
+ final IElementType tokenType = polyadicExpression.getOperationTokenType();
+ final PsiType type = polyadicExpression.getType();
+ final PsiType wrappedExpressionType = wrappedExpression.getType();
if (TypeUtils.isJavaLangString(type) || isArithmeticOperation(tokenType) || isBooleanOperation(tokenType)) {
expectedType = type;
}
else if (isShiftOperation(tokenType)) {
- if (lhs == wrappedExpression) {
- expectedType = unaryNumericPromotion(lhsType);
- }
- else {
- expectedType = unaryNumericPromotion(rhsType);
- }
+ expectedType = unaryNumericPromotion(wrappedExpressionType);
}
- else if (ComparisonUtils.isEqualityComparison(binaryExpression)) {
+ else if (ComparisonUtils.isEqualityComparison(polyadicExpression)) {
// JLS 15.21.1 Numerical Equality Operators == and !=
- final PsiType wrappedExpressionType = wrappedExpression.getType();
if (TypeConversionUtil.isPrimitiveAndNotNull(wrappedExpressionType)) {
expectedType = wrappedExpressionType;
- return;
}
- if (lhs == wrappedExpression) {
- if (TypeConversionUtil.isPrimitiveAndNotNull(rhsType)) {
+ else if (operands.length > 2) {
+ expectedType = PsiPrimitiveType.getUnboxedType(wrappedExpressionType);
+ }
+ else if (operands[0] == wrappedExpression) {
+ if (TypeConversionUtil.isPrimitiveAndNotNull(operands[1].getType())) {
expectedType = PsiPrimitiveType.getUnboxedType(wrappedExpressionType);
- return;
}
- expectedType = TypeUtils.getObjectType(wrappedExpression);
+ else {
+ expectedType = TypeUtils.getObjectType(wrappedExpression);
+ }
}
else {
- if (TypeConversionUtil.isPrimitiveAndNotNull(lhsType)) {
+ if (TypeConversionUtil.isPrimitiveAndNotNull(operands[0].getType())) {
expectedType = PsiPrimitiveType.getUnboxedType(wrappedExpressionType);
- return;
- }
- expectedType = TypeUtils.getObjectType(wrappedExpression);
+ }
+ else {
+ expectedType = TypeUtils.getObjectType(wrappedExpression);
+ }
}
}
else if (ComparisonUtils.isComparisonOperation(tokenType)) {
- if (lhs == wrappedExpression && !TypeConversionUtil.isPrimitiveAndNotNull(lhsType)) {
- lhsType = PsiPrimitiveType.getUnboxedType(lhsType);
- if (lhsType == null) {
- expectedType = null;
- return;
- }
+ if (operands.length != 2) {
+ expectedType = null;
+ return;
}
- if (rhs == wrappedExpression && !TypeConversionUtil.isPrimitiveAndNotNull(rhsType)) {
- rhsType = PsiPrimitiveType.getUnboxedType(rhsType);
- if (rhsType == null) {
- expectedType = null;
+ else if (!TypeConversionUtil.isPrimitiveAndNotNull(wrappedExpressionType)) {
+ if (PsiPrimitiveType.getUnboxedType(wrappedExpressionType) == null) {
return;
}
}
- // JLS 5.6.2 Binary Numeric Promotion
- if (PsiType.DOUBLE.equals(lhsType) || PsiType.DOUBLE.equals(rhsType)) {
- expectedType = PsiType.DOUBLE;
- }
- else if (PsiType.FLOAT.equals(lhsType) || PsiType.FLOAT.equals(rhsType)) {
- expectedType = PsiType.FLOAT;
- }
- else if (PsiType.LONG.equals(lhsType) || PsiType.LONG.equals(rhsType)) {
- expectedType = PsiType.LONG;
- }
- else {
- expectedType = PsiType.INT;
- }
+ expectedType = TypeConversionUtil.binaryNumericPromotion(operands[0].getType(), operands[1].getType());
}
else {
expectedType = null;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
index 6301e83eb0fd..8d52a8619dc5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 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.
@@ -19,8 +19,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleSettingsFacade;
import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.*;
+import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.HardcodedMethodConstants;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -247,20 +247,22 @@ public class ImportUtils {
continue;
}
final PsiElement element = importReference.resolve();
- if (element == null || !(element instanceof PsiPackage)) {
+ if (!(element instanceof PsiPackage)) {
continue;
}
final PsiPackage aPackage = (PsiPackage)element;
- if (!strict) {
- return aPackage.containsClassNamed(shortName);
+ if (!strict && aPackage.containsClassNamed(shortName)) {
+ return true;
}
- final PsiClass[] classes = aPackage.findClassByShortName(shortName, file.getResolveScope());
- for (final PsiClass aClass : classes) {
- final String qualifiedClassName = aClass.getQualifiedName();
- if (qualifiedClassName == null || fqName.equals(qualifiedClassName)) {
- continue;
+ else {
+ final PsiClass[] classes = aPackage.findClassByShortName(shortName, file.getResolveScope());
+ for (final PsiClass aClass : classes) {
+ final String qualifiedClassName = aClass.getQualifiedName();
+ if (qualifiedClassName == null || fqName.equals(qualifiedClassName)) {
+ continue;
+ }
+ return containsConflictingReference(file, qualifiedClassName);
}
- return containsConflictingReference(file, qualifiedClassName);
}
}
return hasJavaLangImportConflict(fqName, file);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java
index af04c02d6e79..5063ef7c2ea7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2006 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 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.
@@ -31,7 +31,7 @@ public class SideEffectChecker {
return visitor.mayHaveSideEffects();
}
- private static class SideEffectsVisitor extends JavaRecursiveElementVisitor {
+ private static class SideEffectsVisitor extends JavaRecursiveElementWalkingVisitor {
private boolean mayHaveSideEffects = false;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java
index e097d58f8301..b8e7b7c183d8 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 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.
@@ -20,6 +20,9 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Set;
public class VariableAccessUtils {
@@ -446,4 +449,43 @@ public class VariableAccessUtils {
}
return child;
}
+
+ public static Set<PsiVariable> collectUsedVariables(PsiElement context) {
+ if (context == null) {
+ return Collections.emptySet();
+ }
+ final VariableCollectingVisitor visitor = new VariableCollectingVisitor();
+ context.accept(visitor);
+ return visitor.getUsedVariables();
+ }
+
+ public static boolean isAnyVariableAssigned(@NotNull Collection<PsiVariable> variables, @Nullable PsiElement context) {
+ if (context == null) {
+ return false;
+ }
+ final VariableAssignedVisitor visitor = new VariableAssignedVisitor(variables, true);
+ context.accept(visitor);
+ return visitor.isAssigned();
+ }
+
+ private static class VariableCollectingVisitor extends JavaRecursiveElementVisitor {
+
+ private final Set<PsiVariable> usedVariables = new HashSet();
+
+ @Override
+ public void visitReferenceExpression(
+ PsiReferenceExpression expression) {
+ super.visitReferenceExpression(expression);
+ final PsiElement target = expression.resolve();
+ if (!(target instanceof PsiVariable)) {
+ return;
+ }
+ final PsiVariable variable = (PsiVariable)target;
+ usedVariables.add(variable);
+ }
+
+ public Set<PsiVariable> getUsedVariables() {
+ return usedVariables;
+ }
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java
index 0a22ef3fde97..279400f3a653 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 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.
@@ -20,16 +20,25 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+import java.util.Collections;
+
public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor {
- @NotNull private final PsiVariable variable;
+ @NotNull private final Collection<PsiVariable> variables;
private final boolean recurseIntoClasses;
private final boolean checkUnaryExpressions;
private boolean assigned = false;
private PsiElement excludedElement = null;
+ public VariableAssignedVisitor(@NotNull Collection<PsiVariable> variables, boolean recurseIntoClasses) {
+ this.variables = variables;
+ checkUnaryExpressions = true;
+ this.recurseIntoClasses = recurseIntoClasses;
+ }
+
public VariableAssignedVisitor(@NotNull PsiVariable variable, boolean recurseIntoClasses) {
- this.variable = variable;
+ variables = Collections.singleton(variable);
final PsiType type = variable.getType();
checkUnaryExpressions = TypeConversionUtil.isNumericType(type);
this.recurseIntoClasses = recurseIntoClasses;
@@ -58,8 +67,11 @@ public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor
}
super.visitAssignmentExpression(assignment);
final PsiExpression lhs = assignment.getLExpression();
- if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
- assigned = true;
+ for (PsiVariable variable : variables) {
+ if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
+ assigned = true;
+ break;
+ }
}
}
@@ -85,8 +97,11 @@ public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor
return;
}
final PsiExpression operand = prefixExpression.getOperand();
- if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
- assigned = true;
+ for (PsiVariable variable : variables) {
+ if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
+ assigned = true;
+ break;
+ }
}
}
@@ -104,8 +119,11 @@ public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor
return;
}
final PsiExpression operand = postfixExpression.getOperand();
- if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
- assigned = true;
+ for (PsiVariable variable : variables) {
+ if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
+ assigned = true;
+ break;
+ }
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java
new file mode 100644
index 000000000000..97adc033c5b1
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2000-2014 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.siyeh.ig.threading;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
+import com.siyeh.ig.psiutils.VariableAccessUtils;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class SharedThreadLocalRandomInspection extends BaseInspection {
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("shared.thread.local.random.display.name");
+ }
+
+ @NotNull
+ @Override
+ protected String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("shared.thread.local.random.problem.descriptor");
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new SharedThreadLocalRandomVisitor();
+ }
+
+ private static class SharedThreadLocalRandomVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+ @NonNls final String name = methodExpression.getReferenceName();
+ if (!"current".equals(name)) {
+ return;
+ }
+ final PsiMethod method = expression.resolveMethod();
+ if (method == null) {
+ return;
+ }
+ final PsiClass aClass = method.getContainingClass();
+ if (!InheritanceUtil.isInheritor(aClass, "java.util.concurrent.ThreadLocalRandom")) {
+ return;
+ }
+ if (isArgumentToMethodCall(expression)) {
+ registerMethodCallError(expression);
+ }
+ else {
+ final PsiVariable variable = assignedToVariable(expression);
+ if (variable instanceof PsiField) {
+ registerMethodCallError(expression);
+ }
+ else if (variable instanceof PsiLocalVariable) {
+ final PsiCodeBlock context = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+ if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, context) ||
+ VariableAccessUtils.variableIsUsedInInnerClass(variable, context)) {
+ registerMethodCallError(expression);
+ }
+ }
+ }
+ }
+
+ private static boolean isArgumentToMethodCall(PsiExpression expression) {
+ final PsiElement parent = ParenthesesUtils.getParentSkipParentheses(expression);
+ if (!(parent instanceof PsiExpressionList)) {
+ return false;
+ }
+ final PsiElement grandParent = parent.getParent();
+ return grandParent instanceof PsiMethodCallExpression;
+ }
+
+ private static PsiVariable assignedToVariable(PsiMethodCallExpression expression) {
+ final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
+ if (parent instanceof PsiVariable) {
+ return (PsiVariable)parent;
+ }
+ if (!(parent instanceof PsiAssignmentExpression)) {
+ return null;
+ }
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
+ final PsiExpression rhs = assignmentExpression.getRExpression();
+ if (!PsiTreeUtil.isAncestor(rhs, expression, false)) {
+ return null;
+ }
+ final PsiExpression lhs = ParenthesesUtils.stripParentheses(assignmentExpression.getLExpression());
+ if (!(lhs instanceof PsiReferenceExpression)) {
+ return null;
+ }
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
+ final PsiElement target = referenceExpression.resolve();
+ if (!(target instanceof PsiVariable)) {
+ return null;
+ }
+ return (PsiVariable)target;
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionBase.java
new file mode 100644
index 000000000000..5b245eccc0a0
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionBase.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2003-2014 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.
+ * 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.siyeh.ig.visibility;
+
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.psi.*;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.ClassUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class LambdaParameterHidingMemberVariableInspectionBase extends BaseInspection {
+
+ @SuppressWarnings("PublicField")
+ public boolean m_ignoreInvisibleFields = true;
+
+ @Override
+ @NotNull
+ public String getID() {
+ return "LambdaParameterHidesMemberVariable";
+ }
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("lambda.parameter.hides.member.variable.display.name");
+ }
+
+ @Override
+ protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
+ return true;
+ }
+
+ @Override
+ @NotNull
+ public String buildErrorString(Object... infos) {
+ final PsiClass aClass = (PsiClass)infos[0];
+ return InspectionGadgetsBundle.message("lambda.parameter.hides.member.variable.problem.descriptor", aClass.getName());
+ }
+
+ @Override
+ public JComponent createOptionsPanel() {
+ final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("parameter.hides.member.variable.ignore.superclass.option"),
+ "m_ignoreInvisibleFields");
+ return optionsPanel;
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new LambdaParameterHidingMemberVariableVisitor();
+ }
+
+ private class LambdaParameterHidingMemberVariableVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitParameter(@NotNull PsiParameter variable) {
+ super.visitParameter(variable);
+ final PsiElement declarationScope = variable.getDeclarationScope();
+ if (!(declarationScope instanceof PsiLambdaExpression)) {
+ return;
+ }
+ final PsiClass aClass = checkFieldName(variable);
+ if (aClass == null) {
+ return;
+ }
+ registerVariableError(variable, aClass);
+ }
+
+ @Nullable
+ private PsiClass checkFieldName(PsiVariable variable) {
+ final String variableName = variable.getName();
+ if (variableName == null) {
+ return null;
+ }
+ PsiClass aClass = ClassUtils.getContainingClass(variable);
+ while (aClass != null) {
+ final PsiField[] fields = aClass.getAllFields();
+ for (PsiField field : fields) {
+ final String fieldName = field.getName();
+ if (!variableName.equals(fieldName)) {
+ continue;
+ }
+ if (!m_ignoreInvisibleFields || ClassUtils.isFieldVisible(field, aClass)) {
+ return aClass;
+ }
+ }
+ aClass = ClassUtils.getContainingClass(aClass);
+ }
+ return null;
+ }
+ }
+} \ No newline at end of file