Issue #2523: Make DetectorOptions as final and immutable

This commit is contained in:
Andrei Selkin 2015-12-15 01:51:50 +03:00 committed by Roman Ivanov
parent bc034f53c0
commit f9ff86c701
6 changed files with 215 additions and 126 deletions

View File

@ -1738,7 +1738,9 @@
<option name="ignorePrivateMethods" value="true" />
</inspection_tool>
<inspection_tool class="ReturnOfDateField" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ReturnOfInnerClass" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ReturnOfInnerClass" enabled="true" level="WARNING" enabled_by_default="true" >
<option name="ignoreNonPublic" value="true" />
</inspection_tool>
<inspection_tool class="ReturnThis" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="ReuseOfLocalVariable" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="ReuseOfLocalVariableJS" enabled="true" level="ERROR" enabled_by_default="true" />

View File

@ -148,6 +148,13 @@
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration[@Image='XMLLogger']//MethodDeclarator[@Image='isReference'] | //ClassOrInterfaceDeclaration[@Image='DetailAST']//MethodDeclarator[@Image='addPreviousSibling'] | //ClassOrInterfaceDeclaration[@Image='AnnotationLocationCheck']//MethodDeclarator[@Image='checkAnnotations'] | //ClassOrInterfaceDeclaration[@Image='PkgControl']//MethodDeclarator[@Image='checkAccess'] | //ClassOrInterfaceDeclaration[@Image='HandlerFactory']//MethodDeclarator[@Image='getHandler']"/>
</properties>
</rule>
<rule ref="rulesets/java/design.xml/AccessorClassGeneration">
<properties>
<!-- We do instantiation by way of private constructors from outside of the constructors
class in DetectorOptions intentionally as it is a whole idea of Builder pattern. -->
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration[@Image='DetectorOptions']"/>
</properties>
</rule>
<rule ref="rulesets/java/design.xml/PreserveStackTrace">
<properties>
<!-- yes we swallow one exception and try to do another attempt, second attempt does not hide cause -->

View File

@ -21,25 +21,26 @@ package com.puppycrawl.tools.checkstyle.checks.regexp;
import java.util.regex.Pattern;
import org.apache.commons.lang3.ObjectUtils;
import com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter;
/**
* Options for a detector.
* @author Oliver Burn
*/
class DetectorOptions {
final class DetectorOptions {
/**
* Flags to compile a regular expression with.
* See {@link Pattern#flags()}.
*/
private final int compileFlags;
private int compileFlags;
/** Used for reporting violations. */
private final AbstractViolationReporter reporter;
private AbstractViolationReporter reporter;
/**
* Format of the regular expression to check for. Default value is pattern that never matches
* any string.
* Format of the regular expression to check for.
*/
private String format = "$.";
private String format;
/** The message to report on detection. If blank, then use the format. */
private String message = "";
/** Minimum number of times regular expression should occur in a file. */
@ -49,82 +50,12 @@ class DetectorOptions {
/** Whether to ignore case when matching. */
private boolean ignoreCase;
/** Used to determine whether to suppress a detected match. */
private MatchSuppressor suppressor = NeverSuppress.INSTANCE;
private MatchSuppressor suppressor;
/** Pattern created from format. Lazily initialized. */
private Pattern pattern;
/**
* Creates an instance.
* @param compileFlags the flags to create the regular expression with.
* @param reporter used to report violations.
*/
DetectorOptions(int compileFlags,
AbstractViolationReporter reporter) {
this.compileFlags = compileFlags;
this.reporter = reporter;
}
/**
* The format to use when matching lines.
* @param format the format to use when matching lines.
* @return current instance
*/
public DetectorOptions setFormat(String format) {
this.format = format;
pattern = null;
return this;
}
/**
* Message to use when reporting a match.
* @param message message to use when reporting a match.
* @return current instance.
*/
public DetectorOptions setMessage(String message) {
this.message = message;
return this;
}
/**
* Set the minimum allowed number of detections.
* @param minimum the minimum allowed number of detections.
* @return current instance
*/
public DetectorOptions setMinimum(int minimum) {
this.minimum = minimum;
return this;
}
/**
* Set the maximum allowed number of detections.
* @param maximum the maximum allowed number of detections.
* @return current instance
*/
public DetectorOptions setMaximum(int maximum) {
this.maximum = maximum;
return this;
}
/**
* Set the suppressor to use.
* @param sup the suppressor to use.
* @return current instance
*/
public DetectorOptions setSuppressor(MatchSuppressor sup) {
suppressor = sup;
return this;
}
/**
* Set whether to ignore case when matching.
* @param ignore whether to ignore case when matching.
* @return current instance
*/
public DetectorOptions setIgnoreCase(boolean ignore) {
ignoreCase = ignore;
pattern = null;
return this;
}
/** Default constructor.*/
private DetectorOptions() { }
/**
* Format of the regular expression.
@ -190,4 +121,107 @@ class DetectorOptions {
pattern = Pattern.compile(format, options);
return pattern;
}
/**
* Returns new Builder object.
* @return Builder object.
*/
static Builder newBuilder() {
return new DetectorOptions().new Builder();
}
/** Class which implements Builder pattern to build DetectorOptions instance. */
public final class Builder {
/**
* Specifies the violation reporter and returns Builder object.
* @param val for reporting violations.
* @return Builder object.
*/
Builder reporter(AbstractViolationReporter val) {
reporter = val;
return this;
}
/**
* Specifies the compile flags to compile a regular expression with
* and returns Builder object.
* @param val the format to use when matching lines.
* @return Builder object.
*/
Builder compileFlags(int val) {
compileFlags = val;
return this;
}
/**
* Specifies the format to use when matching lines and returns Builder object.
* @param val the format to use when matching lines.
* @return Builder object.
*/
Builder format(String val) {
format = val;
return this;
}
/**
* Specifies message to use when reporting a match and returns Builder object.
* @param val message to use when reporting a match.
* @return Builder object.
*/
Builder message(String val) {
message = val;
return this;
}
/**
* Specifies the minimum allowed number of detections and returns Builder object.
* @param val the minimum allowed number of detections.
* @return Builder object.
*/
Builder minimum(int val) {
minimum = val;
return this;
}
/**
* Specifies the maximum allowed number of detections and returns Builder object.
* @param val the maximum allowed number of detections.
* @return Builder object.
*/
Builder maximum(int val) {
maximum = val;
return this;
}
/**
* Specifies whether to ignore case when matching and returns Builder object.
* @param val whether to ignore case when matching.
* @return Builder object.
*/
Builder ignoreCase(boolean val) {
ignoreCase = val;
return this;
}
/**
* Specifies the suppressor to use and returns Builder object.
* @param val the suppressor to use.
* @return current instance
*/
Builder suppressor(MatchSuppressor val) {
suppressor = val;
return this;
}
/**
* Returns new DetectorOptions instance.
* @return DetectorOptions instance.
*/
DetectorOptions build() {
message = ObjectUtils.defaultIfNull(message, "");
suppressor = ObjectUtils.defaultIfNull(suppressor, NeverSuppress.INSTANCE);
return DetectorOptions.this;
}
}
}

View File

@ -32,15 +32,33 @@ import com.puppycrawl.tools.checkstyle.api.FileText;
* @author Oliver Burn
*/
public class RegexpMultilineCheck extends AbstractFileSetCheck {
/** The detection options to use. */
private final DetectorOptions options = new DetectorOptions(Pattern.MULTILINE,
this);
/** The format of the regular expression to match. */
private String format = "$.";
/** The message to report for a match. */
private String message;
/** The minimum number of matches required per file. */
private int minimum;
/** The maximum number of matches required per file. */
private int maximum;
/** Whether to ignore case when matching. */
private boolean ignoreCase;
/** The detector to use. */
private MultilineDetector detector;
@Override
public void beginProcessing(String charset) {
super.beginProcessing(charset);
final DetectorOptions options = DetectorOptions.newBuilder()
.reporter(this)
.compileFlags(Pattern.MULTILINE)
.format(format)
.message(message)
.minimum(minimum)
.maximum(maximum)
.ignoreCase(ignoreCase)
.build();
detector = new MultilineDetector(options);
}
@ -50,42 +68,42 @@ public class RegexpMultilineCheck extends AbstractFileSetCheck {
}
/**
* Set the format of the regular expression to match.
* Sets the format of the regular expression to match.
* @param format the format of the regular expression to match.
*/
public void setFormat(String format) {
options.setFormat(format);
this.format = format;
}
/**
* Set the message to report for a match.
* Sets the message to report for a match.
* @param message the message to report for a match.
*/
public void setMessage(String message) {
options.setMessage(message);
this.message = message;
}
/**
* Set the minimum number of matches required per file.
* Sets the minimum number of matches required per file.
* @param minimum the minimum number of matches required per file.
*/
public void setMinimum(int minimum) {
options.setMinimum(minimum);
this.minimum = minimum;
}
/**
* Set the maximum number of matches required per file.
* Sets the maximum number of matches required per file.
* @param maximum the maximum number of matches required per file.
*/
public void setMaximum(int maximum) {
options.setMaximum(maximum);
this.maximum = maximum;
}
/**
* Set whether to ignore case when matching.
* @param ignore whether to ignore case when matching.
* Sets whether to ignore case when matching.
* @param ignoreCase whether to ignore case when matching.
*/
public void setIgnoreCase(boolean ignore) {
options.setIgnoreCase(ignore);
public void setIgnoreCase(boolean ignoreCase) {
this.ignoreCase = ignoreCase;
}
}

View File

@ -29,14 +29,33 @@ import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
* @author Oliver Burn
*/
public class RegexpSinglelineCheck extends AbstractFileSetCheck {
/** The detection options to use. */
private final DetectorOptions options = new DetectorOptions(0, this);
/** The format of the regular expression to match. */
private String format = "$.";
/** The message to report for a match. */
private String message;
/** The minimum number of matches required per file. */
private int minimum;
/** The maximum number of matches required per file. */
private int maximum;
/** Whether to ignore case when matching. */
private boolean ignoreCase;
/** The detector to use. */
private SinglelineDetector detector;
@Override
public void beginProcessing(String charset) {
super.beginProcessing(charset);
final DetectorOptions options = DetectorOptions.newBuilder()
.reporter(this)
.compileFlags(0)
.format(format)
.message(message)
.minimum(minimum)
.maximum(maximum)
.ignoreCase(ignoreCase)
.build();
detector = new SinglelineDetector(options);
}
@ -50,7 +69,7 @@ public class RegexpSinglelineCheck extends AbstractFileSetCheck {
* @param format the format of the regular expression to match.
*/
public void setFormat(String format) {
options.setFormat(format);
this.format = format;
}
/**
@ -58,7 +77,7 @@ public class RegexpSinglelineCheck extends AbstractFileSetCheck {
* @param message the message to report for a match.
*/
public void setMessage(String message) {
options.setMessage(message);
this.message = message;
}
/**
@ -66,7 +85,7 @@ public class RegexpSinglelineCheck extends AbstractFileSetCheck {
* @param minimum the minimum number of matches required per file.
*/
public void setMinimum(int minimum) {
options.setMinimum(minimum);
this.minimum = minimum;
}
/**
@ -74,14 +93,14 @@ public class RegexpSinglelineCheck extends AbstractFileSetCheck {
* @param maximum the maximum number of matches required per file.
*/
public void setMaximum(int maximum) {
options.setMaximum(maximum);
this.maximum = maximum;
}
/**
* Set whether to ignore case when matching.
* @param ignore whether to ignore case when matching.
* @param ignoreCase whether to ignore case when matching.
*/
public void setIgnoreCase(boolean ignore) {
options.setIgnoreCase(ignore);
public void setIgnoreCase(boolean ignoreCase) {
this.ignoreCase = ignoreCase;
}
}

View File

@ -32,10 +32,17 @@ import com.puppycrawl.tools.checkstyle.api.DetailAST;
* @author Oliver Burn
*/
public class RegexpSinglelineJavaCheck extends Check {
/** The detection options to use. */
private final DetectorOptions options = new DetectorOptions(0, this);
/** The detector to use. */
private SinglelineDetector detector;
/** The format of the regular expression to match. */
private String format = "$.";
/** The message to report for a match. */
private String message;
/** The minimum number of matches required per file. */
private int minimum;
/** The maximum number of matches required per file. */
private int maximum;
/** Whether to ignore case when matching. */
private boolean ignoreCase;
/** Suppress comments. **/
private boolean ignoreComments;
@ -54,22 +61,24 @@ public class RegexpSinglelineJavaCheck extends Check {
return getAcceptableTokens();
}
@Override
public void init() {
super.init();
detector = new SinglelineDetector(options);
}
@Override
public void beginTree(DetailAST rootAST) {
MatchSuppressor supressor = null;
if (ignoreComments) {
options.setSuppressor(new CommentSuppressor(getFileContents()));
}
else {
options.setSuppressor(NeverSuppress.INSTANCE);
supressor = new CommentSuppressor(getFileContents());
}
final DetectorOptions options = DetectorOptions.newBuilder()
.reporter(this)
.compileFlags(0)
.suppressor(supressor)
.format(format)
.message(message)
.minimum(minimum)
.maximum(maximum)
.ignoreCase(ignoreCase)
.build();
final SinglelineDetector detector = new SinglelineDetector(options);
detector.processLines(Arrays.asList(getLines()));
}
@ -78,7 +87,7 @@ public class RegexpSinglelineJavaCheck extends Check {
* @param format the format of the regular expression to match.
*/
public void setFormat(String format) {
options.setFormat(format);
this.format = format;
}
/**
@ -86,7 +95,7 @@ public class RegexpSinglelineJavaCheck extends Check {
* @param message the message to report for a match.
*/
public void setMessage(String message) {
options.setMessage(message);
this.message = message;
}
/**
@ -94,7 +103,7 @@ public class RegexpSinglelineJavaCheck extends Check {
* @param minimum the minimum number of matches required per file.
*/
public void setMinimum(int minimum) {
options.setMinimum(minimum);
this.minimum = minimum;
}
/**
@ -102,15 +111,15 @@ public class RegexpSinglelineJavaCheck extends Check {
* @param maximum the maximum number of matches required per file.
*/
public void setMaximum(int maximum) {
options.setMaximum(maximum);
this.maximum = maximum;
}
/**
* Set whether to ignore case when matching.
* @param ignore whether to ignore case when matching.
* @param ignoreCase whether to ignore case when matching.
*/
public void setIgnoreCase(boolean ignore) {
options.setIgnoreCase(ignore);
public void setIgnoreCase(boolean ignoreCase) {
this.ignoreCase = ignoreCase;
}
/**