rfe #1041590, allow header specification directly in checkstyle config file
This commit is contained in:
parent
510bf2e6a7
commit
d1a2974764
|
|
@ -37,6 +37,8 @@
|
|||
<p class="body">
|
||||
Checks that a source file begins with a specified header. Property <span class="code">
|
||||
headerFile</span> specifies a file that contains the required header.
|
||||
Alternatively, the header specification can be set directly in the
|
||||
<span class="code">header</span> property without the need for an external file.
|
||||
</p>
|
||||
<p class="body">
|
||||
Property <span class="code">ignoreLines</span> specifies the line numbers to
|
||||
|
|
@ -70,6 +72,15 @@ line 5: ////////////////////////////////////////////////////////////////////
|
|||
<td><a href="property_types.html#string">string</a></td>
|
||||
<td><span class="default">null</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>header</td>
|
||||
<td>the required header specified inline. Individual header lines
|
||||
must be separated by the string <span class="code">"\n"</span>
|
||||
(even on platforms with a different line separator),
|
||||
see examples below.</td>
|
||||
<td><a href="property_types.html#string">string</a></td>
|
||||
<td><span class="default">null</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ignoreLines</td>
|
||||
<td>line numbers to ignore</td>
|
||||
|
|
@ -90,6 +101,23 @@ line 5: ////////////////////////////////////////////////////////////////////
|
|||
<property name="ignoreLines" value="2, 3, 4"/>
|
||||
</module>
|
||||
</pre>
|
||||
|
||||
<p class="body">
|
||||
To configure the check to verify that each file starts with the header
|
||||
</p>
|
||||
<pre class="body">
|
||||
// Copyright (C) 2004 MyCompany
|
||||
// All rights reserved
|
||||
</pre>
|
||||
<p class="body">
|
||||
without the need for an external header file:
|
||||
</p>
|
||||
<pre class="body">
|
||||
<module name="Header">
|
||||
<property name="header" value="// Copyright (C) 2004 MyCompany\n// All rights reserved"/>
|
||||
</module>
|
||||
</pre>
|
||||
|
||||
<h4>Package</h4>
|
||||
<p class="body">
|
||||
com.puppycrawl.tools.checkstyle.checks
|
||||
|
|
@ -100,7 +128,7 @@ line 5: ////////////////////////////////////////////////////////////////////
|
|||
</p>
|
||||
<a name="RegexpHeader"></a> <h2>RegexpHeader</h2> <h4>Description</h4>
|
||||
<p class="body">
|
||||
Checks the header of a source file against a header file that contains a <a href="http://jakarta.apache.org/regexp/apidocs/org/apache/regexp/RE.html">regular
|
||||
Checks the header of a source file against a header that contains a <a href="http://jakarta.apache.org/regexp/apidocs/org/apache/regexp/RE.html">regular
|
||||
expression</a> for each line of the source header.
|
||||
</p>
|
||||
<p class="body">
|
||||
|
|
@ -109,7 +137,7 @@ line 5: ////////////////////////////////////////////////////////////////////
|
|||
information is not static.
|
||||
</p>
|
||||
<p class="body">
|
||||
For example, consider the following header file:
|
||||
For example, consider the following header:
|
||||
</p>
|
||||
<pre class="body">
|
||||
line 1: ^/{71}$
|
||||
|
|
@ -150,6 +178,15 @@ line 14: ^ \*/
|
|||
<td><a href="property_types.html#string">string</a></td>
|
||||
<td><span class="default">null</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>header</td>
|
||||
<td>the required header specified inline. Individual header lines
|
||||
must be separated by the string <span class="code">"\n"</span>
|
||||
(even on platforms with a different line separator), and regular
|
||||
expressions must not span multiple lines.</td>
|
||||
<td><a href="property_types.html#string">string</a></td>
|
||||
<td><span class="default">null</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>multiLines</td>
|
||||
<td>line numbers to repeat (zero or more times)</td>
|
||||
|
|
@ -169,6 +206,21 @@ line 14: ^ \*/
|
|||
<module name="RegexpHeader">
|
||||
<property name="headerFile" value="java.header"/>
|
||||
<property name="multiLines" value="10, 13"/>
|
||||
</module>
|
||||
</pre>
|
||||
<p class="body">
|
||||
To configure the check to verify that each file starts with the header
|
||||
</p>
|
||||
<pre class="body">
|
||||
^// Copyright \(C\) (\d\d\d\d -)? 2004 MyCompany$
|
||||
^// All rights reserved$
|
||||
</pre>
|
||||
<p class="body">
|
||||
without the need for an external header file:
|
||||
</p>
|
||||
<pre class="body">
|
||||
<module name="RegexpHeader">
|
||||
<property name="header" value="^// Copyright \(C\) (\d\d\d\d -)? 2004 MyCompany$\n^// All rights reserved$"/>
|
||||
</module>
|
||||
</pre>
|
||||
<p class="body">
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
<p>Checkstyle 3</p>
|
||||
<ul>
|
||||
<li><a href="#release3_5">Release 3.5</a></li>
|
||||
<li><a href="#release3_4">Release 3.4</a></li>
|
||||
<li><a href="#release3_3">Release 3.3</a></li>
|
||||
<li><a href="#release3_2">Release 3.2</a></li>
|
||||
|
|
@ -68,6 +69,19 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<p class="body">
|
||||
New features:
|
||||
</p>
|
||||
<ul>
|
||||
<li class="body">
|
||||
Java parser supports JDK 1.5 source files (metadata,
|
||||
enhanced for loops, generics, enums).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<a name="release3_5"></a>
|
||||
<h2>Release 3.5</h2>
|
||||
|
||||
<p class="body">
|
||||
New features:
|
||||
</p>
|
||||
|
|
@ -125,6 +139,10 @@ checkstyle-user</a>).</li>
|
|||
and abstract methods.
|
||||
(request 993922 and bug 1002849).</li>
|
||||
|
||||
<li class="body">Header and RegexpHeader checks allow header
|
||||
specification directly in the checkstyle configuration file,
|
||||
not only in an external file (request 1041590).
|
||||
|
||||
<li class="body">com.puppycrawl.tools.checkstyle.gui.Main accepts an
|
||||
optional file name in the command line.
|
||||
(request 1000102).</li>
|
||||
|
|
|
|||
|
|
@ -22,12 +22,16 @@ package com.puppycrawl.tools.checkstyle.checks;
|
|||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Check;
|
||||
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
|
||||
import com.puppycrawl.tools.checkstyle.api.Utils;
|
||||
|
||||
import org.apache.commons.beanutils.ConversionException;
|
||||
import org.apache.regexp.RE;
|
||||
|
||||
/**
|
||||
* Abstract super class for header checks.
|
||||
|
|
@ -61,25 +65,100 @@ public abstract class AbstractHeaderCheck extends Check
|
|||
return;
|
||||
}
|
||||
|
||||
checkHeaderNotInitialized();
|
||||
|
||||
// load the file
|
||||
Reader headerReader = null;
|
||||
try {
|
||||
final LineNumberReader lnr =
|
||||
new LineNumberReader(new FileReader(aFileName));
|
||||
final ArrayList lines = new ArrayList();
|
||||
while (true) {
|
||||
final String l = lnr.readLine();
|
||||
if (l == null) {
|
||||
break;
|
||||
}
|
||||
lines.add(l);
|
||||
}
|
||||
mHeaderLines = (String[]) lines.toArray(new String[0]);
|
||||
headerReader = new FileReader(aFileName);
|
||||
loadHeader(headerReader);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new ConversionException(
|
||||
"unable to load header file " + aFileName, ex);
|
||||
}
|
||||
finally {
|
||||
if (headerReader != null) {
|
||||
try {
|
||||
headerReader.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new ConversionException(
|
||||
"unable to close header file " + aFileName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the header to check against. Individual lines in the header
|
||||
* must be separated by '\n' characters.
|
||||
* @param aHeader header content to check against.
|
||||
* @throws ConversionException if the header cannot be interpreted
|
||||
*/
|
||||
public void setHeader(String aHeader)
|
||||
{
|
||||
if ((aHeader == null) || (aHeader.trim().length() == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkHeaderNotInitialized();
|
||||
|
||||
// in JDK 1.4 we'd simply do aHeader.replaceAll("\\\\n", "\n");
|
||||
final RE re = Utils.getRE("\\\\n");
|
||||
final String headerExpandedNewLines = re.subst(aHeader, "\n");
|
||||
|
||||
final Reader headerReader = new StringReader(headerExpandedNewLines);
|
||||
try {
|
||||
loadHeader(headerReader);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new ConversionException(
|
||||
"unable to load header", ex);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
headerReader.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// shouldn't happen with StringReader
|
||||
throw new ConversionException(
|
||||
"unable to close header", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before initializing the header.
|
||||
* @throws ConversionException if header has already been set
|
||||
*/
|
||||
private void checkHeaderNotInitialized()
|
||||
{
|
||||
if (mHeaderLines != null) {
|
||||
throw new ConversionException(
|
||||
"header has already been set - "
|
||||
+ "set either header or headerFile, not both");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load header to check against from a Reader into mHeaderLines.
|
||||
* @param aHeaderReader delivers the header to check against
|
||||
* @throws IOException if
|
||||
*/
|
||||
private void loadHeader(final Reader aHeaderReader) throws IOException
|
||||
{
|
||||
final LineNumberReader lnr = new LineNumberReader(aHeaderReader);
|
||||
final ArrayList lines = new ArrayList();
|
||||
while (true) {
|
||||
final String l = lnr.readLine();
|
||||
if (l == null) {
|
||||
break;
|
||||
}
|
||||
lines.add(l);
|
||||
}
|
||||
mHeaderLines = (String[]) lines.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ import com.puppycrawl.tools.checkstyle.api.Utils;
|
|||
* <property name="multiLines" value="10, 13"/>
|
||||
*</module>
|
||||
* </pre>
|
||||
* <p><u>Note</u>: ignoreLines property was removed you should use ^.*$ regexp
|
||||
* for line to ignore it.
|
||||
* <p><u>Note</u>: ignoreLines property has been removed from this check to
|
||||
* simplify it. The regular expression "^.*$" can be used to ignore a line.
|
||||
* </p>
|
||||
*
|
||||
* @author Lars Kühne
|
||||
|
|
@ -129,6 +129,25 @@ public class RegexpHeaderCheck extends AbstractHeaderCheck
|
|||
throws ConversionException
|
||||
{
|
||||
super.setHeaderFile(aFileName);
|
||||
initHeaderRegexps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the header to check against. Individual lines in the header
|
||||
* must be separated by '\n' characters.
|
||||
* @param aHeader header content to check against.
|
||||
* @throws ConversionException if the header cannot be loaded or one line
|
||||
* is not a regexp.
|
||||
*/
|
||||
public void setHeader(String aHeader)
|
||||
{
|
||||
super.setHeader(aHeader);
|
||||
initHeaderRegexps();
|
||||
}
|
||||
|
||||
/** Initializes {@link #mHeaderRegexps} from {@link #mHeaderLines}. */
|
||||
private void initHeaderRegexps()
|
||||
{
|
||||
final String[] headerLines = getHeaderLines();
|
||||
if (headerLines != null) {
|
||||
mHeaderRegexps = new RE[headerLines.length];
|
||||
|
|
@ -139,7 +158,7 @@ public class RegexpHeaderCheck extends AbstractHeaderCheck
|
|||
}
|
||||
catch (RESyntaxException ex) {
|
||||
throw new ConversionException(
|
||||
"line " + i + " in header file is not a regexp");
|
||||
"line " + i + " in header specification is not a regular expression");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,33 @@ public class HeaderCheckTest extends BaseCheckTestCase
|
|||
verify(checkConfig, getPath("InputScopeAnonInner.java"), expected);
|
||||
}
|
||||
|
||||
public void testInlineRegexpHeader()
|
||||
throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(RegexpHeaderCheck.class);
|
||||
checkConfig.addAttribute("header", "^/*$\\n// .*\\n// Created: 2002\\n^//.*\\n^//.*");
|
||||
final String[] expected = {
|
||||
"3: Line does not match expected header line of '// Created: 2002'."
|
||||
};
|
||||
verify(checkConfig, getPath("InputScopeAnonInner.java"), expected);
|
||||
}
|
||||
|
||||
public void testFailureForMultilineRegexp()
|
||||
throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(RegexpHeaderCheck.class);
|
||||
checkConfig.addAttribute("header", "^(.*\\n.*)");
|
||||
try {
|
||||
createChecker(checkConfig);
|
||||
fail("Checker creation should not succeed when regexp spans multiple lines");
|
||||
}
|
||||
catch (CheckstyleException ex) {
|
||||
// expected exception
|
||||
}
|
||||
}
|
||||
|
||||
public void testRegexpHeaderIgnore() throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
|
|
@ -122,7 +149,7 @@ public class HeaderCheckTest extends BaseCheckTestCase
|
|||
}
|
||||
}
|
||||
|
||||
public void testIllegalArgs()
|
||||
public void testNonExistingHeaderFile()
|
||||
throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
|
|
|
|||
Loading…
Reference in New Issue