Skip to content

Commit

Permalink
Merge 240a0a2 into a47eb3c
Browse files Browse the repository at this point in the history
  • Loading branch information
pbaranchikov committed Mar 21, 2016
2 parents a47eb3c + 240a0a2 commit 774a69c
Show file tree
Hide file tree
Showing 10 changed files with 544 additions and 0 deletions.
1 change: 1 addition & 0 deletions eclipsecs-sevntu-plugin/src/checkstyle_packages.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<package name="naming"/>
<package name="sizes"/>
<package name="whitespace"/>
<package name="misc"/>
</package>
<package name="grammars"/>
</package>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PrimitiveLiteralsCaseCheck.name = Primitive literals case check
PrimitiveLiteralsCaseCheck.desc = <p>Checks for the same case of primitive literals, for example: 50.0f and 50.0F</p>
PrimitiveLiteralsCaseCheck.requiredCase = Whether to use uppercase ("upper" value) or lowercase ("lower" value) for primitive literals
PrimitiveLiteralsCaseCheck.tokens = Tokens to restrict
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE checkstyle-metadata PUBLIC
"-//eclipse-cs//DTD Check Metadata 1.1//EN"
"http://eclipse-cs.sourceforge.net/dtds/checkstyle-metadata_1_1.dtd">
<checkstyle-metadata>
<rule-group-metadata name="SevNTU checks" priority="501">
<rule-metadata name="%PrimitiveLiteralsCaseCheck.name" internal-name="PrimitiveLiteralsCaseCheck" parent="TreeWalker">
<alternative-name internal-name="com.github.sevntu.checkstyle.checks.misc.PrimitiveLiteralsCaseCheck" />
<description>%PrimitiveLiteralsCaseCheck.desc</description>
<property-metadata name="requiredCase" datatype="String" default-value="upper">
<description>%PrimitiveLiteralsCaseCheck.requiredCase</description>
</property-metadata>
<!--
TODO: switch to SingleSelect, when check migratest to main project
<property-metadata name="option" datatype="SingleSelect" default-value="UPPER">
<description>%PrimitiveLiteralsCaseCheck.option</description>
<enumeration option-provider="com.github.sevntu.checkstyle.CharacterCase"/>
</property-metadata>
-->
<property-metadata name="tokens" datatype="MultiCheck"
default-value="NUM_LONG,NUM_FLOAT,NUM_DOUBLE">
<description>%PrimitiveLiteralsCaseCheck.tokens</description>
<enumeration>
<property-value-option value="NUM_LONG"/>
<property-value-option value="NUM_FLOAT"/>
<property-value-option value="NUM_DOUBLE"/>
</enumeration>
</property-metadata>
</rule-metadata>
</rule-group-metadata>
</checkstyle-metadata>
2 changes: 2 additions & 0 deletions sevntu-checks/checkstyle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#checkstyle.suppressions.file=/home/pavel/workspace/checkstyle_new/sevntu.checkstyle/sevntu-checks/suppressions.xml
#checkstyle.suppressions.file=${config_loc}/suppressions.xml
checkstyle.suppressions.file=suppressions.xml
checkstyle.header.file=https://raw.githubusercontent.com/checkstyle/checkstyle/master/config/java.header
checkstyle.regexp.header.file=https://raw.githubusercontent.com/checkstyle/checkstyle/master/config/java_regexp.header
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2016 the original author or authors.
//
// 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.github.sevntu.checkstyle.checks.misc;

import java.util.EnumMap;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.beanutils.ConversionException;

import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;

/**
* Check, performing checks for literal numeric type specifiers case. Numeric
* float constants cat be represented in different ways:
* <ul>
* <li><code>50.0f</code>
* <li><code>50.0F</code>
* </ul>
* The check prevents from mixing these two styles, allowing user to restrict
* check usage for only certain types of literal numeric constants, specified in
* "tokens" property:
* <ul>
* <li>NUM_LONG
* <li>NUM_FLOAT
* <li>NUM_DOUBLE
* </ul>
* Check can force euther upper or lower case of the constant, using "option"
* property:
* <ul>
* <li>upper
* <li>lower
* </ul>
* <br>
* Check is full equivalent to already existing check UpperEll, when specifying
* option to "upper" and tokens to "NUM_LONG" <br>
* Default properties are upper case and all the available tokens: NUM_LONG,
* NUM_FLOAT, NUM_DOUBLE
*
* @author Pavel Baranchikov
* @see {@link com.puppycrawl.tools.checkstyle.checks.UpperEllCheck}
*
*/
public class PrimitiveLiteralsCaseCheck extends AbstractCheck {

/**
* Message key to show when specifier should be in upper case, but is in
* lower.
*/
protected static final String MSG_UPPER_CASE = "primitige.literal.case.upper";
/**
* Message key to show when specifier should be in lower case, but is in
* upper.
*/
protected static final String MSG_LOWER_CASE = "primitige.literal.case.lower";
/**
* Processors for different required character cases.
*/
private final Map<CharacterCase, CaseValidationProcessor> processors;
/**
* Required character case.
*/
private CharacterCase requiredCase = CharacterCase.UPPER;

/**
* Constructs the check.
*/
public PrimitiveLiteralsCaseCheck() {
processors = new EnumMap<CharacterCase, CaseValidationProcessor>(
CharacterCase.class);
processors.put(CharacterCase.UPPER, new UpperCaseValidationProcessor());
processors.put(CharacterCase.LOWER, new LowerCaseValidationProcessor());
}

/**
* Sets requiredCase value from the configuration.
*
* @param requiredCaseStr string representation for required case.
*/
public void setRequiredCase(String requiredCaseStr) {
try {
this.requiredCase = CharacterCase.valueOf(requiredCaseStr.trim()
.toUpperCase(Locale.ENGLISH));
}
catch (IllegalArgumentException iae) {
throw new ConversionException("unknown character case: "
+ requiredCaseStr, iae);
}
}

@Override
public int[] getDefaultTokens() {
return getAcceptableTokens();
}

@Override
public int[] getAcceptableTokens() {
return new int[] {
TokenTypes.NUM_DOUBLE,
TokenTypes.NUM_FLOAT,
TokenTypes.NUM_LONG,
};
}

@Override
public int[] getRequiredTokens() {
return new int[0];
}

@Override
public void visitToken(DetailAST ast) {
final String astString = ast.getText();
final char specifier = astString.charAt(astString.length() - 1);
if (Character.isDigit(specifier)) {
// For primitives, ending with digit - no validation should be applied.
return;
}
final CaseValidationProcessor processor = processors.get(requiredCase);
final boolean correctSpecifier = processor.isSpecifierCorrect(specifier);
if (!correctSpecifier) {
log(ast.getLineNo(),
ast.getColumnNo() + astString.length() - 1,
processor.getMsgKey(),
processor.getAdjustedSpecifier(specifier));
}
}

/**
* Enum describes character casess.
*/
protected enum CharacterCase {
/**
* Upper case character, i.e. {@code F}, {@code L}, {@code D}.
*/
UPPER,
/**
* Lower case character, i.e. {@code f}, {@code l}, {@code d}.
*/
LOWER;
}

/**
* Interface to hold functionality specific for the characther case.
*/
private interface CaseValidationProcessor {
/**
* Returns error message key for of this processor.
*
* @return erorr message key
*/

String getMsgKey();

/**
* Method determines, whether the specifier is wrong. This is not the
* same as just inverting the case, when specifier is correct, because
* there may be no specifier at all, which is not wrong case.
*
* @param specifier
* primitive specifier
* @return <code>true</code> if the specifier is wrong
*/
boolean isSpecifierCorrect(char specifier);

/**
* Method corrects the specifier to the one it should be when the option
* is selected active.
*
* @param specifier
* specifier to convert to correct case
* @return correct specifier
*/
char getAdjustedSpecifier(char specifier);
}

/**
* Processor for upper case required.
*/
private static class UpperCaseValidationProcessor implements CaseValidationProcessor {
@Override
public char getAdjustedSpecifier(char specifier) {
return Character.toUpperCase(specifier);
}

@Override
public String getMsgKey() {
return MSG_UPPER_CASE;
}

@Override
public boolean isSpecifierCorrect(char specifier) {
return Character.isUpperCase(specifier);
}

}

/**
* Processor for lower case required.
*/
private static class LowerCaseValidationProcessor implements CaseValidationProcessor {

@Override
public char getAdjustedSpecifier(char specifier) {
return Character.toLowerCase(specifier);
}

@Override
public String getMsgKey() {
return MSG_LOWER_CASE;
}

@Override
public boolean isSpecifierCorrect(char specifier) {
return Character.isLowerCase(specifier);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2016 the original author or authors.
//
// 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
////////////////////////////////////////////////////////////////////////////////

/**
* Contains the <span class="xdocspagetitle">Miscelaneous</span> checks that
* cannot be brought to any other check type.
*/
package com.github.sevntu.checkstyle.checks.misc;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
primitige.literal.case.upper=Should use uppercase ''{0}''.
primitige.literal.case.lower=Should use lowercase ''{0}''.
Loading

0 comments on commit 774a69c

Please sign in to comment.