pmd/pmd — pull request #6 by witherspore (2012-09-04 03:36:24+00:00)
Title: Support in CPD for IgnoreAnnotations and SuppressWarnings("CPD-START")

All,

These are some CPD features many people in my company have been wanting for the last few years. Additionally, I moved the JavaTokenizer to a more OO model. Unit Tests are pretty explanatory

Pull request for: https://github.com/tacitknowledge/pmd/commit/179ab9d708a7fcb777ed45cda196ca1fec315804

There is an upstream merge as well, but it could be ignore. https://github.com/tacitknowledge/pmd/commit/23748bcc55c58383a059d8fac21d7a8f3ff357a9

The last author had started that:

/*	I'm doing a sort of State pattern thing here where	this goes into "discarding" mode when it hits an import or package	keyword and goes back into "accumulate mode" when it hits a semicolon.	This could probably be turned into some objects.
```

I created a Discarder interface, and a couple implementations. One handles keywords/tokens like import and package. Another discards annotation blocks. Another turns CPD on and off based on Strings within an annotation e.g. @SuppressWarnings("CPD-START") and @SuppressWarnings("CPD-END).

There have been two features desired by myself and my colleagues strongly.
1. Ability to ignore sections of source code, such as switch/case statements or parameterized factories.
2. Ability to ignore annotations. More and more modern frameworks use annotations on classes and methods, which can be very redundant and trigger CPD matches.

Just to illustrate, here is a parametrized factory example that can cause a false positive if you ignore literals (String and int values):
```
if ("A".equals(input)) return new A(1);
if ("B".equals(input)) return new A(2);
if ("C".equals(input)) return new A(3);
if ("D".equals(input)) return new A(4);
if ("E".equals(input)) return new A(5);
```
False positives cause the CPD reports to be a burden to review and read. Many people start ignoring them when the first 20 entries are 'acceptable'.

For annotations, with J2EE (CDI, Transaction Handling, etc) and Spring (everything) become very redundant. Often classes or methods have the same 5-6 lines of annotations. This causes false positives.

For CPD-START and CPD-END, it would be much more desirable to use comments rather than annotations. However, the parser drops comments and they can not be processed by the JavaTokenizer. The current approach forces entire methods or classes to be skipped, rather than some blocks. However, I feel its an improvement in cases like parameterized factories or case/switch statements where I don't want them polluting my results.