IG: rework inspection for performance and accuracy (IDEA-163797)
authorBas Leijdekkers <basleijdekkers@gmail.com>
Fri, 11 Nov 2016 19:11:29 +0000 (20:11 +0100)
committerBas Leijdekkers <basleijdekkers@gmail.com>
Sat, 12 Nov 2016 07:18:19 +0000 (08:18 +0100)
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ArrayContentsAccessedVisitor.java [deleted file]
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java
plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java

index 3575b14170bfc30d4f862fb8f9332e09aa7b9205..f9c634545cbd9e2823b4356062b392b012ddfe4c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2016 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.
@@ -17,14 +17,14 @@ package com.siyeh.ig.bugs;
 
 import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
 import com.intellij.psi.*;
-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.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.CloneUtils;
-import com.siyeh.ig.psiutils.VariableAccessUtils;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
@@ -84,12 +84,13 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
         return;
       }
       final PsiClass containingClass = PsiUtil.getTopLevelClass(field);
-      if (!checkVariable(field, containingClass)) {
+      if (!shouldCheckVariable(field, containingClass)) {
         return;
       }
-      final boolean written = arrayContentsAreWritten(field, containingClass);
-      final boolean read = arrayContentsAreRead(field, containingClass);
-      if (written == read) {
+      final ArrayReadWriteVisitor visitor = new ArrayReadWriteVisitor(field, !isSimpleArrayExpression(field.getInitializer()));
+      containingClass.accept(visitor);
+      final boolean written = visitor.isWritten();
+      if (!visitor.isReferenced() || written == visitor.isRead()) {
         return;
       }
       registerFieldError(field, Boolean.valueOf(written));
@@ -99,66 +100,58 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
     public void visitLocalVariable(@NotNull PsiLocalVariable variable) {
       super.visitLocalVariable(variable);
       final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
-      if (!checkVariable(variable, codeBlock)) {
+      if (!shouldCheckVariable(variable, codeBlock)) {
         return;
       }
-      final boolean written = arrayContentsAreWritten(variable, codeBlock);
-      final boolean read = arrayContentsAreRead(variable, codeBlock);
-      if (written == read) {
+      final ArrayReadWriteVisitor visitor = new ArrayReadWriteVisitor(variable, !isSimpleArrayExpression(variable.getInitializer()));
+      codeBlock.accept(visitor);
+      final boolean written = visitor.isWritten();
+      if (!visitor.isReferenced() || written == visitor.isRead()) {
         return;
       }
       registerVariableError(variable, Boolean.valueOf(written));
     }
 
-    private static boolean checkVariable(PsiVariable variable,
-                                         PsiElement context) {
-      if (context == null) {
-        return false;
-      }
-      final PsiType type = variable.getType();
-      if (type.getArrayDimensions() == 0) {
-        return false;
-      }
-      if (VariableAccessUtils.variableIsAssigned(variable, context)) {
+    private static boolean shouldCheckVariable(PsiVariable variable, PsiElement context) {
+      return context != null && variable.getType().getArrayDimensions() != 0 && !isComplexArrayExpression(variable.getInitializer());
+    }
+
+    static boolean isComplexArrayExpression(PsiExpression expression) {
+      expression = ParenthesesUtils.stripParentheses(expression);
+      if (expression == null) {
         return false;
       }
-      if (VariableAccessUtils.variableIsAssignedFrom(variable, context)) {
-        return false;
+      if (expression instanceof PsiNewExpression) {
+        final PsiNewExpression newExpression = (PsiNewExpression)expression;
+        final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer();
+        return isComplexArrayExpression(arrayInitializer);
       }
-      if (VariableAccessUtils.variableIsReturned(variable, context)) {
+      else if (expression instanceof PsiArrayInitializerExpression) {
+        final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression)expression;
+        for (PsiExpression initializer : arrayInitializerExpression.getInitializers()) {
+          if (isComplexArrayExpression(initializer)) {
+            return true;
+          }
+        }
         return false;
       }
-      return !VariableAccessUtils.variableIsUsedInArrayInitializer(variable, context);
-    }
-
-    private static boolean arrayContentsAreWritten(PsiVariable variable,
-                                                   PsiElement context) {
-      if (VariableAccessUtils.arrayContentsAreAssigned(variable, context)) {
-        return true;
-      }
-      if (!isDefaultArrayInitializer(variable.getInitializer())) {
-        return true;
+      else if (expression instanceof PsiReferenceExpression) {
+        return expression.getType() instanceof PsiArrayType;
       }
-      return variableIsWritten(variable, context);
-    }
-
-    private static boolean arrayContentsAreRead(PsiVariable variable,
-                                                PsiElement context) {
-      if (VariableAccessUtils.arrayContentsAreAccessed(variable, context)) {
+      else if (expression instanceof PsiArrayAccessExpression) {
         return true;
       }
-      if (isPossiblyReferenceThatIsReadLater(variable.getInitializer())) {
-        return true;
+      else if (expression instanceof PsiTypeCastExpression) {
+        final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)expression;
+        return isComplexArrayExpression(typeCastExpression.getOperand());
       }
-      return variableIsRead(variable, context);
-    }
-
-    private static boolean isPossiblyReferenceThatIsReadLater(PsiExpression initializer) {
-      if (initializer == null || initializer instanceof PsiNewExpression || initializer instanceof PsiArrayInitializerExpression) {
-        return false;
+      else if (expression instanceof PsiConditionalExpression) {
+        final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)expression;
+        return isComplexArrayExpression(conditionalExpression.getThenExpression()) ||
+               isComplexArrayExpression(conditionalExpression.getElseExpression());
       }
-      if (initializer instanceof PsiMethodCallExpression) {
-        final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)initializer;
+      else if (expression instanceof PsiMethodCallExpression) {
+        final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
         final PsiMethod method = methodCallExpression.resolveMethod();
         if (method == null) {
           return true;
@@ -167,23 +160,28 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
           return false;
         }
         @NonNls final String name = method.getName();
-        if (!"copyOf".equals(name) && !"copyOfRange".equals(name)) {
-          return true;
+        if ("copyOf".equals(name) || "copyOfRange".equals(name)) {
+          final PsiClass aClass = method.getContainingClass();
+          if (aClass != null && CommonClassNames.JAVA_UTIL_ARRAYS.equals(aClass.getQualifiedName())) {
+            return false;
+          }
+        }
+        else if ("toArray".equals(name) && InheritanceUtil.isInheritor(method.getContainingClass(), "java.util.Collection")) {
+          return false;
         }
-        final PsiClass aClass = method.getContainingClass();
-        return aClass == null || !CommonClassNames.JAVA_UTIL_ARRAYS.equals(aClass.getQualifiedName());
+        return true;
       }
       return true;
     }
 
-    private static boolean isDefaultArrayInitializer(PsiExpression initializer) {
+    static boolean isSimpleArrayExpression(PsiExpression initializer) {
       if (initializer == null) {
         return true;
       }
       if (initializer instanceof PsiNewExpression) {
         final PsiNewExpression newExpression = (PsiNewExpression)initializer;
         final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer();
-        return arrayInitializer == null || isDefaultArrayInitializer(arrayInitializer);
+        return arrayInitializer == null || isSimpleArrayExpression(arrayInitializer);
       }
       if (initializer instanceof PsiArrayInitializerExpression) {
         final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression)initializer;
@@ -193,136 +191,147 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
       return false;
     }
 
-    private static boolean variableIsWritten(@NotNull PsiVariable variable, @NotNull PsiElement context) {
-      final VariableReadWriteVisitor visitor = new VariableReadWriteVisitor(variable, true);
-      context.accept(visitor);
-      return visitor.isPassed();
-    }
-
-    private static boolean variableIsRead(@NotNull PsiVariable variable, @NotNull PsiElement context) {
-      final VariableReadWriteVisitor visitor =
-        new VariableReadWriteVisitor(variable, false);
-      context.accept(visitor);
-      return visitor.isPassed();
-    }
-
-    private static class VariableReadWriteVisitor extends JavaRecursiveElementWalkingVisitor {
+    private static class ArrayReadWriteVisitor extends JavaRecursiveElementWalkingVisitor {
+      private final PsiVariable myVariable;
+      private boolean myWritten;
+      private boolean myRead = false;
+      private boolean myIsReferenced = false;
 
-      @NotNull
-      private final PsiVariable variable;
-      private final boolean write;
-      private boolean passed;
-
-      private VariableReadWriteVisitor(@NotNull PsiVariable variable, boolean write) {
-        this.variable = variable;
-        this.write = write;
+      ArrayReadWriteVisitor(@NotNull PsiVariable variable, boolean written) {
+        myVariable = variable;
+        myWritten = written;
       }
 
       @Override
-      public void visitElement(@NotNull PsiElement element) {
-        if (!passed) {
-          super.visitElement(element);
+      public void visitReferenceExpression(PsiReferenceExpression expression) {
+        if (myWritten && myRead) {
+          return;
         }
-      }
-
-      @Override
-      public void visitBinaryExpression(PsiBinaryExpression expression) {
-        super.visitBinaryExpression(expression);
-        if (write || passed) {
+        super.visitReferenceExpression(expression);
+        final PsiElement target = expression.resolve();
+        if (target != myVariable) {
           return;
         }
-        final IElementType tokenType = expression.getOperationTokenType();
-        if (!JavaTokenType.EQEQ.equals(tokenType) && !JavaTokenType.NE.equals(tokenType)) {
+        if (PsiUtil.isAccessedForWriting(expression)) {
+          final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
+          if (parent instanceof PsiAssignmentExpression) {
+            final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
+            final PsiExpression rhs = assignmentExpression.getRExpression();
+            if (isComplexArrayExpression(rhs)) {
+              myWritten = true;
+              myRead = true;
+            }
+            else if (!isSimpleArrayExpression(rhs)) {
+              myWritten = true;
+            }
+          }
           return;
         }
-        final PsiExpression lhs = expression.getLOperand();
-        if (!(lhs instanceof PsiBinaryExpression)) {
-          if (VariableAccessUtils.mayEvaluateToVariable(lhs, variable)) {
-            passed = true;
+        myIsReferenced = true;
+        PsiElement parent = getParent(expression);
+        if (parent instanceof PsiArrayAccessExpression) {
+          PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression)parent;
+          parent = getParent(parent);
+          while (parent instanceof PsiArrayAccessExpression) {
+            arrayAccessExpression = (PsiArrayAccessExpression)parent;
+            parent = getParent(parent);
+          }
+          final PsiType type = arrayAccessExpression.getType();
+          if (type != null) {
+            final int dimensions = type.getArrayDimensions();
+            if (dimensions > 0 && dimensions != myVariable.getType().getArrayDimensions()) {
+              myWritten = true;
+            }
+          }
+          if (PsiUtil.isAccessedForWriting(arrayAccessExpression)) {
+            myWritten = true;
+          }
+          if (PsiUtil.isAccessedForReading(arrayAccessExpression)) {
+            myRead = true;
           }
         }
-        final PsiExpression rhs = expression.getROperand();
-        if (!(rhs instanceof PsiBinaryExpression)) {
-          if (VariableAccessUtils.mayEvaluateToVariable(rhs, variable)) {
-            passed = true;
+        else if (parent instanceof PsiReferenceExpression) {
+          final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)parent;
+          final String name = referenceExpression.getReferenceName();
+          if ("length".equals(name) || ("clone".equals(name) && referenceExpression.getParent() instanceof PsiMethodCallExpression)) {
+            myRead = true;
           }
         }
-      }
-
-      @Override
-      public void visitMethodCallExpression(
-        @NotNull PsiMethodCallExpression call) {
-        if (passed) {
-          return;
+        else if (parent instanceof PsiForeachStatement) {
+          final PsiForeachStatement foreachStatement = (PsiForeachStatement)parent;
+          final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
+          if (PsiTreeUtil.isAncestor(iteratedValue, expression, false)) {
+            myRead = true;
+          }
         }
-        super.visitMethodCallExpression(call);
-        final PsiExpressionList argumentList = call.getArgumentList();
-        final PsiExpression[] arguments = argumentList.getExpressions();
-        for (int i = 0; i < arguments.length; i++) {
-          final PsiExpression argument = arguments[i];
-          if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
-            if (write && i == 0 && isCallToSystemArraycopy(call)) {
-              return;
-            }
-            if (!write && i == 2 && isCallToSystemArraycopy(call)) {
-              return;
+        else if (parent instanceof PsiExpressionList) {
+          final PsiExpressionList expressionList = (PsiExpressionList)parent;
+          parent = parent.getParent();
+          if (parent instanceof PsiMethodCallExpression) {
+            final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)parent;
+            final PsiMethod method = methodCallExpression.resolveMethod();
+            if (method != null) {
+              final PsiClass aClass = method.getContainingClass();
+              if (aClass != null) {
+                final String methodName = method.getName();
+                final String qualifiedName = aClass.getQualifiedName();
+                if ("java.lang.System".equals(qualifiedName)) {
+                  if ("arraycopy".equals(methodName)) {
+                    final PsiExpression[] expressions = expressionList.getExpressions();
+                    if (expressions.length == 5) {
+                      if (PsiTreeUtil.isAncestor(expressions[0], expression, false)) {
+                        myRead = true;
+                        return;
+                      }
+                      else if (PsiTreeUtil.isAncestor(expressions[2], expression, false)) {
+                        myWritten = true;
+                        return;
+                      }
+                    }
+                  }
+                }
+                else if (CommonClassNames.JAVA_UTIL_ARRAYS.equals(qualifiedName)) {
+                  if ("fill".equals(methodName) || "parallelPrefix".equals(methodName) || "parallelSetAll".equals(methodName) ||
+                      "parallelSort".equals(methodName) || "setAll".equals(methodName) || "sort".equals(methodName)) {
+                    myWritten = true;
+                  }
+                  else {
+                    myRead = true;
+                  }
+                  return;
+                }
+              }
             }
-            passed = true;
           }
+          myRead = true;
+          myWritten = true;
         }
-      }
-
-      private static boolean isCallToSystemArraycopy(PsiMethodCallExpression call) {
-        final PsiReferenceExpression methodExpression = call.getMethodExpression();
-        @NonNls final String name = methodExpression.getReferenceName();
-        if (!"arraycopy".equals(name)) {
-          return false;
-        }
-        final PsiExpression qualifier = methodExpression.getQualifierExpression();
-        if (!(qualifier instanceof PsiReferenceExpression)) {
-          return false;
-        }
-        final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
-        final PsiElement element = referenceExpression.resolve();
-        if (!(element instanceof PsiClass)) {
-          return false;
+        else {
+          myWritten = true;
+          myRead = true;
         }
-        return "java.lang.System".equals(((PsiClass)element).getQualifiedName());
       }
 
-      @Override
-      public void visitNewExpression(@NotNull PsiNewExpression newExpression) {
-        if (passed) {
-          return;
+      private static PsiElement getParent(PsiElement element) {
+        PsiElement parent = element.getParent();
+        while (parent instanceof PsiParenthesizedExpression ||
+               parent instanceof PsiTypeCastExpression ||
+               parent instanceof PsiConditionalExpression) {
+          parent = parent.getParent();
         }
-        super.visitNewExpression(newExpression);
-        visitPsiCall(newExpression);
+        return parent;
       }
 
-      @Override
-      public void visitEnumConstant(PsiEnumConstant enumConstant) {
-        if (passed) {
-          return;
-        }
-        super.visitEnumConstant(enumConstant);
-        visitPsiCall(enumConstant);
+      public boolean isRead() {
+        return myRead;
       }
 
-      private void visitPsiCall(PsiCall newExpression) {
-        final PsiExpressionList argumentList = newExpression.getArgumentList();
-        if (argumentList == null) {
-          return;
-        }
-        final PsiExpression[] arguments = argumentList.getExpressions();
-        for (final PsiExpression argument : arguments) {
-          if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
-            passed = true;
-          }
-        }
+      public boolean isWritten() {
+        return myWritten;
       }
 
-      public boolean isPassed() {
-        return passed;
+      public boolean isReferenced() {
+        return myIsReferenced;
       }
     }
   }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ArrayContentsAccessedVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ArrayContentsAccessedVisitor.java
deleted file mode 100644 (file)
index a14da9a..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2003-2011 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.psiutils;
-
-import com.intellij.psi.*;
-import com.siyeh.HardcodedMethodConstants;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-class ArrayContentsAccessedVisitor extends JavaRecursiveElementWalkingVisitor {
-
-  private boolean accessed;
-  private final PsiVariable variable;
-
-  ArrayContentsAccessedVisitor(@NotNull PsiVariable variable) {
-    this.variable = variable;
-  }
-
-  @Override
-  public void visitForeachStatement(
-    @NotNull PsiForeachStatement statement) {
-    if (accessed) {
-      return;
-    }
-    super.visitForeachStatement(statement);
-    final PsiExpression qualifier = statement.getIteratedValue();
-    if (!(qualifier instanceof PsiReferenceExpression)) {
-      return;
-    }
-    final PsiReferenceExpression referenceExpression =
-      (PsiReferenceExpression)qualifier;
-    final PsiElement target = referenceExpression.resolve();
-    if (variable.equals(target)) {
-      accessed = true;
-    }
-  }
-
-  @Override
-  public void visitArrayAccessExpression(
-    PsiArrayAccessExpression arrayAccessExpression) {
-    if (accessed) {
-      return;
-    }
-    super.visitArrayAccessExpression(arrayAccessExpression);
-    final PsiElement parent = arrayAccessExpression.getParent();
-    if (parent instanceof PsiAssignmentExpression) {
-      final PsiAssignmentExpression assignmentExpression =
-        (PsiAssignmentExpression)parent;
-      final PsiExpression lhs = assignmentExpression.getLExpression();
-      if (lhs.equals(arrayAccessExpression)) {
-        return;
-      }
-    }
-    final PsiExpression arrayExpression =
-      arrayAccessExpression.getArrayExpression();
-    if (!(arrayExpression instanceof PsiReferenceExpression)) {
-      return;
-    }
-    final PsiReferenceExpression referenceExpression =
-      (PsiReferenceExpression)arrayExpression;
-    final PsiElement target = referenceExpression.resolve();
-    if (variable.equals(target)) {
-      accessed = true;
-    }
-  }
-
-  @Override
-  public void visitReferenceExpression(PsiReferenceExpression expression) {
-    if (accessed) {
-      return;
-    }
-    super.visitReferenceExpression(expression);
-    @NonNls final String referenceName = expression.getReferenceName();
-    if (!"length".equals(referenceName)) {
-      return;
-    }
-    final PsiExpression qualifier = expression.getQualifierExpression();
-    if (!(qualifier instanceof PsiReferenceExpression)) {
-      return;
-    }
-    final PsiReferenceExpression referenceExpression =
-      (PsiReferenceExpression)qualifier;
-    final PsiElement target = referenceExpression.resolve();
-    if (variable.equals(target)) {
-      accessed = true;
-    }
-  }
-
-  @Override
-  public void visitMethodCallExpression(PsiMethodCallExpression expression) {
-    if (accessed) {
-      return;
-    }
-    super.visitMethodCallExpression(expression);
-    final PsiReferenceExpression methodExpression =
-      expression.getMethodExpression();
-    final String methodName = methodExpression.getReferenceName();
-    if (!HardcodedMethodConstants.CLONE.equals(methodName)) {
-      return;
-    }
-    final PsiExpressionList argumentList = expression.getArgumentList();
-    if (argumentList.getExpressions().length != 0) {
-      return;
-    }
-    final PsiExpression qualifier =
-      methodExpression.getQualifierExpression();
-    if (!(qualifier instanceof PsiReferenceExpression)) {
-      return;
-    }
-    final PsiReferenceExpression referenceExpression =
-      (PsiReferenceExpression)qualifier;
-    final PsiElement target = referenceExpression.resolve();
-    if (variable.equals(target)) {
-      accessed = true;
-    }
-  }
-
-  public boolean isAccessed() {
-    return accessed;
-  }
-}
index 60b58ff8dede53e214cf0f91b743b666b65af2d6..bbf23dc6fa8a32fc9d7f5ebb4326876ee1857a26 100644 (file)
@@ -150,17 +150,6 @@ public class VariableAccessUtils {
     return visitor.isVariableValueUsed();
   }
 
-  public static boolean arrayContentsAreAccessed(
-    @NotNull PsiVariable variable, @Nullable PsiElement context) {
-    if (context == null) {
-      return false;
-    }
-    final ArrayContentsAccessedVisitor visitor =
-      new ArrayContentsAccessedVisitor(variable);
-    context.accept(visitor);
-    return visitor.isAccessed();
-  }
-
   public static boolean arrayContentsAreAssigned(
     @NotNull PsiVariable variable, @Nullable PsiElement context) {
     if (context == null) {
index 394723ffddaff4ca51a607ec7ef4b709f67ee129..167fdd57dbb97da7403fdc47cffbd5344f0f01f3 100644 (file)
@@ -1,8 +1,13 @@
 package com.siyeh.igtest.bugs.mismatched_array_read_write;
 
+import java.util.*;
+
+import static java.lang.System.arraycopy;
+
 public class MismatchedArrayReadWrite {
     private int[] <warning descr="Contents of array 'foo' are written to, but never read">foo</warning> = new int[3];
     private int[] <warning descr="Contents of array 'bar' are read, but never written to">bar</warning>;
+    private int[] IVAL_3 = {3}; // strictly written, but warned about by "Unused declaration" inspection
 
     public void bar()
     {
@@ -65,6 +70,20 @@ public class MismatchedArrayReadWrite {
             }
         }
     }
+
+    void bar10(int[] is) {
+        int[] <warning descr="Contents of array 'js' are written to, but never read">js</warning> = new int[is.length];
+        arraycopy(is, 0, js, 0, is.length);
+        int[] <warning descr="Contents of array 'ks' are read, but never written to">ks</warning> = new int[is.length];
+        arraycopy(ks, 0, is, 0, is.length);
+    }
+
+    public void bar11() {
+        final int[][] <warning descr="Contents of array 'allResults' are written to, but never read">allResults</warning> = new int[10][10];
+        for (int row = 0; row < 10; row++) {
+            allResults[row] = new int[9];
+        }
+    }
 }
 class Test{
     public void bar(){
@@ -83,7 +102,6 @@ class Test{
     private void testStuff() {
         int[][] array = new int[2][2];
         array[0][1]++;
-        System.out.println(array[0][1]);
     }
 
     void foo1() {
@@ -196,4 +214,53 @@ class TestIDEA128098 {
       myPatterns = patterns;
     }
   }
+
+  void m(boolean b, String[] ts) {
+    Object[] <warning descr="Contents of array 'ss' are read, but never written to">ss</warning> = new String[10];
+    for (String s : b ? (String[])(ss) : ts) {
+
+    }
+  }
+
+  void m1(List<String> list) {
+    String[] ss = list.toArray(new String[0]);
+    System.out.println(ss[0]);
+  }
+
+  void m2(Object[] otherArr) {
+    Object[] <warning descr="Contents of array 'arr' are written to, but never read">arr</warning> = new Object[10];
+    Arrays.fill(arr, "null");
+  }
+
+  void m3() {
+    String[] <warning descr="Contents of array 'ss' are read, but never written to">ss</warning> = new String[1];
+    System.out.println(Arrays.toString(ss));
+  }
+}
+class Ball {
+  private String[] names;
+
+  Ball() {
+    names = new String[] {
+      "tennisball",
+      "football",
+      "basketball"
+    };
+  }
+
+  public String toString() {
+    return Arrays.toString(names);
+  }
+}
+class ParentRecorder {
+  private final int[] parents;
+
+  public ParentRecorder(int[] parents) {
+    this.parents = parents;
+    Arrays.fill(parents, -1);
+  }
+
+  public void treeEdge(int e, int g) {
+    parents[e] = g;
+  }
 }
\ No newline at end of file