Skip to content

[java] ForLoopCanBeForeach NPE when looping on this object #800

@oowekyala

Description

@oowekyala

Affects PMD Version: 6.0.0

Rule: ForLoopCanBeForeach

Description: The rule should report loops that are iterated on this if possible. For now it considers neither this.iterator() nor just iterator(). Using this.iterator() like in the following code sample yields a NPE with the following stacktrace:

Caused by: java.lang.NullPointerException
	at net.sourceforge.pmd.lang.java.rule.bestpractices.ForLoopCanBeForeachRule.getIterableDeclOfIteratorLoop(ForLoopCanBeForeachRule.java:244)
	at net.sourceforge.pmd.lang.java.rule.bestpractices.ForLoopCanBeForeachRule.visit(ForLoopCanBeForeachRule.java:60)
	at net.sourceforge.pmd.lang.java.ast.ASTForStatement.jjtAccept(ASTForStatement.java:21)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:424)
	at net.sourceforge.pmd.lang.java.ast.ASTStatement.jjtAccept(ASTStatement.java:21)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:436)
	at net.sourceforge.pmd.lang.java.ast.ASTBlockStatement.jjtAccept(ASTBlockStatement.java:21)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:432)
	at net.sourceforge.pmd.lang.java.ast.ASTBlock.jjtAccept(ASTBlock.java:25)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:256)
	at net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration.jjtAccept(ASTMethodDeclaration.java:31)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:120)
	at net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration.jjtAccept(ASTClassOrInterfaceBodyDeclaration.java:41)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:116)
	at net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody.jjtAccept(ASTClassOrInterfaceBody.java:21)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:92)
	at net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration.jjtAccept(ASTClassOrInterfaceDeclaration.java:33)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:232)
	at net.sourceforge.pmd.lang.java.ast.ASTTypeDeclaration.jjtAccept(ASTTypeDeclaration.java:35)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:212)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visitAll(AbstractJavaRule.java:39)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.apply(AbstractJavaRule.java:27)
	at net.sourceforge.pmd.RuleSet.apply(RuleSet.java:502)
	at net.sourceforge.pmd.RuleSets.apply(RuleSets.java:143)
	at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:181)
	at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:95)
	... 20 more

Code Sample demonstrating the issue:

import java.util.Iterator;
class Foo<T> implements Iterable<T> {

  @Override
  public Iterator<T> iterator() {
    return null;
  }

  private void fofo() {
    for (Iterator<T> it = iterator(); it.hasNext();) {
      T item = it.next();
    }
    for (Iterator<T> it = this.iterator(); it.hasNext();) {
      T item = it.next();
    }
  }
}

Running PMD through: CLI

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:bugPMD crashes or fails to analyse a file.a:false-negativePMD doesn't flag a problematic piece of code

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions