Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added NewlineAtEndOfFile check, contributed by Christopher Lenz
- Loading branch information
Showing
2 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
91 changes: 91 additions & 0 deletions
91
src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LineSeparatorOption.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// checkstyle: Checks Java source code for adherence to a set of rules. | ||
// Copyright (C) 2001-2002 Oliver Burn | ||
// | ||
// This library is free software; you can redistribute it and/or | ||
// modify it under the terms of the GNU Lesser General Public | ||
// License as published by the Free Software Foundation; either | ||
// version 2.1 of the License, or (at your option) any later version. | ||
// | ||
// This library is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
// Lesser General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU Lesser General Public | ||
// License along with this library; if not, write to the Free Software | ||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
//////////////////////////////////////////////////////////////////////////////// | ||
package com.puppycrawl.tools.checkstyle.checks; | ||
|
||
import java.util.Map; | ||
import java.util.HashMap; | ||
|
||
/** | ||
* Represents the options for line separator settings. | ||
* | ||
* @author lkuehne | ||
* @see NewlineAtEndOfFileCheck | ||
*/ | ||
public final class LineSeparatorOption extends AbstractOption | ||
{ | ||
/** maps from a string representation to an option */ | ||
private static final Map STR_TO_OPT = new HashMap(); | ||
|
||
/** Windows-style line separators **/ | ||
public static final LineSeparatorOption CRLF = | ||
new LineSeparatorOption("crlf", "\r\n"); | ||
|
||
/** Mac-style line separators **/ | ||
public static final LineSeparatorOption CR = | ||
new LineSeparatorOption("cr", "\r"); | ||
|
||
/** Unix-style line separators **/ | ||
public static final LineSeparatorOption LF = | ||
new LineSeparatorOption("lf", "\n"); | ||
|
||
/** System default line separators **/ | ||
public static final LineSeparatorOption SYSTEM = new LineSeparatorOption( | ||
"system", System.getProperty("line.separator")); | ||
|
||
/** the line separator representation */ | ||
private final String mLineSeparator; | ||
|
||
/** | ||
* Creates a new <code>LineSeparatorOption</code> instance. | ||
* @param aStrRep the string representation | ||
* @param aSep the line separator, e.g. "\r\n" | ||
*/ | ||
private LineSeparatorOption(String aStrRep, String aSep) | ||
{ | ||
super(aStrRep); | ||
mLineSeparator = aSep; | ||
} | ||
|
||
/** | ||
* @param aBytes a bytes array to check | ||
* @return if aBytes is equal to the byte representation | ||
* of this line separator | ||
*/ | ||
public boolean matches(byte[] aBytes) | ||
{ | ||
final String s = new String(aBytes); | ||
return s.equals(mLineSeparator); | ||
} | ||
|
||
/** | ||
* @return the length of the file separator, | ||
* e.g. 1 for CR, 2 for CRLF, ... | ||
*/ | ||
public int length() | ||
{ | ||
return mLineSeparator.length(); | ||
} | ||
|
||
/** @see com.puppycrawl.tools.checkstyle.checks.AbstractOption */ | ||
protected Map getStrToOpt() | ||
{ | ||
return STR_TO_OPT; | ||
} | ||
|
||
} |
170 changes: 170 additions & 0 deletions
170
src/checkstyle/com/puppycrawl/tools/checkstyle/checks/NewlineAtEndOfFileCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// checkstyle: Checks Java source code for adherence to a set of rules. | ||
// Copyright (C) 2001-2002 Oliver Burn | ||
// | ||
// This library is free software; you can redistribute it and/or | ||
// modify it under the terms of the GNU Lesser General Public | ||
// License as published by the Free Software Foundation; either | ||
// version 2.1 of the License, or (at your option) any later version. | ||
// | ||
// This library is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
// Lesser General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU Lesser General Public | ||
// License along with this library; if not, write to the Free Software | ||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
//////////////////////////////////////////////////////////////////////////////// | ||
package com.puppycrawl.tools.checkstyle.checks; | ||
|
||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.io.RandomAccessFile; | ||
|
||
import com.puppycrawl.tools.checkstyle.Defn; | ||
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; | ||
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage; | ||
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher; | ||
import com.puppycrawl.tools.checkstyle.api.LocalizedMessages; | ||
import org.apache.commons.beanutils.ConversionException; | ||
|
||
/** | ||
* <p> | ||
* Checks that there is a newline at the end of each file. | ||
* </p> | ||
* <p> | ||
* An example of how to configure the check is: | ||
* </p> | ||
* <pre> | ||
* <module name="NewlineAtEndOfFile"/></pre> | ||
* <p> | ||
* This will check against the platform-specific default line separator. | ||
* </p> | ||
* <p> | ||
* It is also possible to enforce the use of a specific line-separator across | ||
* platforms, with the 'lineSeparator' property: | ||
* </p> | ||
* <pre> | ||
* <module name="NewlineAtEndOfFile"> | ||
* <property name="lineSeparator" value="lf"/> | ||
* </module></pre> | ||
* <p> | ||
* Valid values for the 'lineSeparator' property are 'system' (system default), | ||
* 'crlf' (windows), 'cr' (mac) and 'lf' (unix). | ||
* </p> | ||
* | ||
* @author Christopher Lenz | ||
* @author lkuehne | ||
* @version 1.0 | ||
*/ | ||
public class NewlineAtEndOfFileCheck | ||
extends AbstractFileSetCheck | ||
{ | ||
/** the line separator to check against. */ | ||
private LineSeparatorOption mLineSeparator = | ||
LineSeparatorOption.SYSTEM; | ||
|
||
/** @see com.puppycrawl.tools.checkstyle.api.Check */ | ||
public int[] getDefaultTokens() | ||
{ | ||
return new int[0]; | ||
} | ||
|
||
/** | ||
* @see com.puppycrawl.tools.checkstyle.api.FileSetCheck#process | ||
*/ | ||
public void process(File[] aFiles) | ||
{ | ||
final File[] files = filter(aFiles); | ||
final MessageDispatcher dispatcher = getMessageDispatcher(); | ||
for (int i = 0; i < files.length; i++) { | ||
final File file = files[i]; | ||
final String path = file.getPath(); | ||
dispatcher.fireFileStarted(path); | ||
RandomAccessFile randomAccessFile = null; | ||
try { | ||
randomAccessFile = new RandomAccessFile(file, "r"); | ||
if (!endsWithNewline(randomAccessFile)) { | ||
log(0, "noNewlineAtEOF", path); | ||
} | ||
} | ||
catch (IOException e) { | ||
logIOException(e); | ||
} | ||
finally { | ||
if (randomAccessFile != null) { | ||
try { | ||
randomAccessFile.close(); | ||
} | ||
catch (IOException e) { | ||
logIOException(e); | ||
} | ||
} | ||
} | ||
final LocalizedMessages messageList = getMessageCollector(); | ||
final LocalizedMessage[] messages = messageList.getMessages(); | ||
dispatcher.fireErrors(path, messages); | ||
dispatcher.fireFileFinished(path); | ||
} | ||
} | ||
|
||
/** | ||
* Sets the line separator to one of 'crlf', 'lf' or 'cr'. | ||
* | ||
* @param aLineSeparator The line separator to set | ||
* @throws IllegalArgumentException If the specified line separator is not | ||
* one of 'crlf', 'lf' or 'cr' | ||
*/ | ||
public void setLineSeparator(String aLineSeparator) | ||
{ | ||
AbstractOption option = | ||
LineSeparatorOption.SYSTEM.decode(aLineSeparator); | ||
|
||
if (option == null) { | ||
throw new ConversionException("unable to parse " + aLineSeparator); | ||
} | ||
|
||
mLineSeparator = (LineSeparatorOption) option; | ||
} | ||
|
||
/** | ||
* Checks whether the content provided by the Reader ends with the platform | ||
* specific line separator. | ||
* @param aRandomAccessFile The reader for the content to check | ||
* @return boolean Whether the content ends with a line separator | ||
* @throws IOException When an IO error occurred while reading from the | ||
* provided reader | ||
*/ | ||
private boolean endsWithNewline(RandomAccessFile aRandomAccessFile) | ||
throws IOException | ||
{ | ||
final int len = mLineSeparator.length(); | ||
if (aRandomAccessFile.length() < len) { | ||
return false; | ||
} | ||
aRandomAccessFile.seek(aRandomAccessFile.length() - len); | ||
final byte lastBytes[] = new byte[len]; | ||
aRandomAccessFile.read(lastBytes); | ||
return mLineSeparator.matches(lastBytes); | ||
} | ||
|
||
/** | ||
* Helper method to log an IO exception. | ||
* @param aEx the exception that occured | ||
*/ | ||
private void logIOException(IOException aEx) | ||
{ | ||
String[] args = null; | ||
String key = "general.fileNotFound"; | ||
if (!(aEx instanceof FileNotFoundException)) { | ||
args = new String[] {aEx.getMessage()}; | ||
key = "general.exception"; | ||
} | ||
LocalizedMessage message = | ||
new LocalizedMessage(0, Defn.CHECKSTYLE_BUNDLE, key, args); | ||
getMessageCollector().add(message); | ||
} | ||
|
||
} |