<?xml version="1.0" encoding="UTF-8"?>
<test-data
    xmlns="http://pmd.sourceforge.net/rule-tests"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">

    <test-code>
        <description>simple unused private field</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    private String foo;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private field referenced in another field's initializer</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private String foo;
    private String bar = foo;
    void buz() {
        bar = bar + 1;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private field with field of same name in anonymous inner class</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    private String foo;
    void baz() {
        Runnable r = new Runnable() {
            public void run() {
                String foo = "buz";
            }
        };
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>field is used semantically before it's declared syntactically</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    void bar() {
        foo[0] = foo[0] + 1;
    }
    private int[] foo;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private field referenced via 'this' modifier</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private String foo;
    void bar() {
        bar = this.foo;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private referenced by anonymous inner class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private static final String FOO = "foo";
    public Runnable bar() {
        return new Runnable() {
            public void run() {
                FOO.toString();
            }
        };
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>interface sanity test</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public interface Foo {
    public static final String FOO = "FOO";
    public boolean equals(Object another);
    public int hashCode();
    public String toString();
}
        ]]></code>
    </test-code>

    <test-code>
        <description>unused private field in static inner class</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    public static class Services {
        private String x;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private field referenced in nonstatic inner class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private int x;
    private class Bar {
        void baz() {
            x = x + 2;
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>unused private static field</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    private static String foo;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private static final referenced with qualifier</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private static final int BAR = 2;
    int x = Foo.BAR;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>unused private field after class decl</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    public class Foo {}
    private int x;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>two unused private fields in separate inner classes</description>
        <expected-problems>2</expected-problems>
        <code><![CDATA[
public class Foo {
    public class Foo {private int x;}
    public class Bar {private int x;}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>method param shadows unused private field</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    private int value;
    int doSomething(int value) {
        return value + 1;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private field referenced via 'this' not shadowed by param of same name</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private int x;
    public Foo(int x) {
        this.x= this.x + 1;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>don't catch public fields</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public static final int FOO = 1;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>instantiate self and reference private field on other object</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private int x;
    void foo() {
        Foo foo = new Foo();
        foo.x = foo.x + 2;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>don't count Serialization fields as being unused</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.io.*;
public class Foo {
    private static final ObjectStreamField[] serialPersistentFields = {new ObjectStreamField("foo", String.class)};
}
        ]]></code>
    </test-code>

    <test-code>
        <description>an assignment does not a usage make</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    private int x;
    void bar() {
        x = 4;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>assignment to field member is a usage</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private Foo x = new Foo();
    void bar() {
        x.y = 42;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>assignment to field member using this modifier is a usage</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private Foo x = new Foo();
    void bar() {
        this.x.y = 42;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>this.foo++ shouldn't throw an NPE, but isn't a usage</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    private int x;
    void bar() {
        this.x++;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>super.foo++ shouldn't throw an NPE</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    void bar() {
        super.x++;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>SuppressWarnings("unused") unused private field</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    @SuppressWarnings("unused")
    private String foo;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>631681, private field is accessed by outer class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class XPathFunctionContext {

    private class Singleton {
        private String foo = "";
    }

    public String getFoo() {
        return (new Singleton()).foo;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>631681, private field in singleton is accessed by outer class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class XPathFunctionContext {

    private static class Singleton {
        private static XPathFunctionContext instance = new XPathFunctionContext();
    }

    public static XPathFunctionContext getInstance() {
        return Singleton.instance;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1188 False positive in UnusedPrivateField</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public enum Operation
{
    LEFT( Action.PRIVATE_MOVE ), RIGHT( Action.PRIVATE_MOVE ), STOP( Action.PRIVATE_STAY );

    private final int action;

    private Operation(final int action)
    {
        this.action = action;
    }

    public int getAction()
    {
        return action;
    }

    private static final class Action
    {
        private static final int PRIVATE_STAY = 0;
        private static final int PRIVATE_MOVE = 1;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private field in inner class accessed as method call</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class InnerPrivateFieldCall {
    int method() {
        return Inner.FIELD.length();
    }
    static class Inner {
        private static final String FIELD = "";
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>private field in inner class accessed by another inner class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class InnerPrivateFieldInAnotherInner {
    static class InnerUsing {
        int method() {
            return InnerDeclaring.INNER_FIELD;
        }
    }
    static class InnerDeclaring {
        private static int INNER_FIELD;
    }
}
        ]]></code>
     </test-code>

     <test-code>
        <description>#1302 False Positive: UnusedPrivateField when accessed by inner class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class UnusedPrivateFieldClass
{
    private int m_number; // UnusedPrivateField incorrectly errors

    public void increment()
    {
        m_number++; // Write
    }

    public User getUser()
    {
        return new User(this);
    }

    public static class User
    {
        private UnusedPrivateFieldClass m_bugTest;
        private int m_number;

        private User(UnusedPrivateFieldClass bugTest)
        {
            m_bugTest = bugTest;
            m_number = bugTest.m_number; // Read
        }

        public boolean isValid()
        {
            return m_bugTest.m_number == m_number;
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1420 UnusedPrivateField: Ignore fields if using lombok - 1</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
@lombok.Data
public class Foo {
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1420 UnusedPrivateField: Ignore fields if using lombok - 2</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.Data;
@Data
public class Foo {
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1420 UnusedPrivateField: Ignore fields if using lombok - 3</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.Data;
@Data
public class Foo {
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1420 UnusedPrivateField: Ignore fields if using lombok - 4</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.Getter;
@Getter
public class Foo {
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1420 UnusedPrivateField: Ignore fields if using lombok - 5</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.Getter;
public class Foo {
    @Getter private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1420 UnusedPrivateField: Ignore fields if using lombok - 6</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.Getter;
public class Foo {
    @Getter(lazy=true) private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1420 UnusedPrivateField: Ignore fields if using lombok - 7</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
@lombok.Data
public class Foo {
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#907 UnusedPrivateField false-positive with @FXML - 1</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import javafx.fxml.FXML;
import javafx.scene.control.TabPane;

public class NodeInfoPanelController {
    @FXML
    private TabPane nodeInfoTabPane;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#907 UnusedPrivateField false-positive with @FXML - 2</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    @Deprecated
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#907 UnusedPrivateField false-positive with @FXML - 3</description>
        <expected-problems>0</expected-problems> <!-- since #4100 any annotation present won't trigger the rule anymore -->
        <code><![CDATA[
public class Foo {
    @Deprecated
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1428 False positive in UnusedPrivateField when local variable hides member variable</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.junit.Test;
import org.junit.BeforeClass;
public class IssueUnusedPrivateField {

    private static Object helper;   // PMD warns unused

    @BeforeClass
    public static void setUpClass() {
        helper = new Object();
    }

    @Test
    public void testSomething() {
        String str = helper.toString();     // used here
        System.out.println("str = " + str);

        String helper = "some new string";  // hidden here
        System.out.println("helper = " + helper);
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1190 [java] UnusedLocalVariable/UnusedPrivateField false-positive</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.io.InputStream;

public class IssueUnusedPrivateField {

    private InputStream is;

    public IssueUnusedPrivateField(InputStream is) {
        this.is = is;
    }

    public void testSomething() {
        try (is) {
            System.out.println("foo!");
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1703 UnusedPrivateField: False-positive with @Delegate</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.experimental.Delegate;

public class Foo {
    @Delegate private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1952 [java] UnusedPrivateField not triggering if @Value annotation present</description>
        <expected-problems>0</expected-problems> <!-- since #4100 any annotation present won't trigger the rule anymore -->
        <code><![CDATA[
import somewhere.Value; // 3rd party Value annotation, ie not lombok

public class Foo {

    @Value
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#2673 UnusedPrivateField false positive with lombok annotation EqualsAndHashCode</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public class Foo {
    private String bar;
}
        ]]></code>
    </test-code>
    <test-code>
        <description>#2673 UnusedPrivateField false positive with lombok annotation EqualsAndHashCode</description>
        <expected-problems>0</expected-problems> <!-- since #4100 any annotation present won't trigger the rule anymore -->
        <code><![CDATA[
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class Foo {
    private String bar;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>False positive with field used in unary expression #3671</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private int counter;
    public void skip(int n) {
        while (counter++ < n) {
            System.out.println("Skipping");
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>False positive when referenced from within inner class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private static final String OUTER_CONSTANT = "";

    private static final class Empty {
        private static final class Inner {
            public boolean isEmpty(String s) {
                return OUTER_CONSTANT.equals(s);
            }
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#3824 #3825 Do not flag fields annotated with @Id, @EmbeddedId, or @Version</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Version;

@Entity
@Table(name = "my_table")
public class MyTable implements Serializable {
   private static final long serialVersionUID = 1L;

   @Id
   @Column(name = "id", nullable = false)
   private long m_id;

   @Version
   @Column(name = "optimistic_lock", nullable = false)
   private short m_optimisticLock;

   public MyTable() {
      // nothing to do
   }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Do not flag Mockito fields that are injected into test target</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.mockito.Spy;
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.springframework.boot.test.mock.mockito.MockBean;

public class MyTest {
   @Mock
   private Object mock;

   @MockBean
   private Object bean;

   @Spy
   private Object spy;

   @InjectMocks
   private Object target;

   void test() {
      target.methodToTest();
   }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4037 false positive with Spring @SpyBean</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.springframework.boot.test.mock.mockito.SpyBean;
import java.security.Provider.Service;
public class C {
    @SpyBean
    private Service service; 
}
        ]]></code>
    </test-code>
    
    <test-code>
        <description>[java] UnusedPrivateField - false positive with Lombok @ToString.Include #4033</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.ToString;

@ToString
public class C {
    @ToString.Include
    private int a;  // Should not report a warning in this line
}
]]></code>
    </test-code>

    <test-code>
        <description>[java] UnusedPrivateField doesn't find annotated unused private fields anymore #4166 (default)</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.WebElement;

class ClassWithUnusedField {
    @FindBy(id = "myId")
    private WebElement myElement;
}
]]></code>
    </test-code>

    <test-code>
        <description>[java] UnusedPrivateField doesn't find annotated unused private fields anymore #4166 (default, other annotation)</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
class ClassWithUnusedField {
    @Deprecated
    private String unusedField;
}
]]></code>
    </test-code>

    <test-code>
        <description>[java] UnusedPrivateField doesn't find annotated unused private fields anymore #4166 (configuration)</description>
        <rule-property name="reportForAnnotations">java.lang.Deprecated,org.openqa.selenium.support.FindBy</rule-property>
        <expected-problems>2</expected-problems>
        <expected-linenumbers>6,9</expected-linenumbers>
        <code><![CDATA[
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

class ClassWithUnusedField {
    @Deprecated
    private String unusedField;

    @FindBy(id = "whatEverId")
    private WebElement myElement;
}
]]></code>
    </test-code>

    <test-code>
        <description>#3626 FN within anonymous class</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>3</expected-linenumbers>
        <code><![CDATA[
public class Tester {
    Object anonymousClass = new Object() {
        private int x = 2021; // Unused, should report a warning
    };
}
]]></code>
    </test-code>
</test-data>
