Skip to content

Commit f020066

Browse files
committed
Issue #2109: CLI should print a file name where exception is happen
1 parent 346387c commit f020066

9 files changed

Lines changed: 144 additions & 85 deletions

File tree

config/pmd.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@
186186
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration[@Image='Main']"/>
187187
</properties>
188188
</rule>
189+
<rule ref="rulesets/java/logging-java.xml/AvoidPrintStackTrace">
190+
<properties>
191+
<!-- it is ok to use print stack trace in CLI class -->
192+
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration[@Image='Main']"/>
193+
</properties>
194+
</rule>
189195

190196
<rule ref="rulesets/java/migrating.xml"/>
191197

@@ -252,6 +258,12 @@
252258
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration[@Image='PackageObjectFactory']"/>
253259
</properties>
254260
</rule>
261+
<rule ref="rulesets/java/strictexception.xml/AvoidCatchingGenericException">
262+
<properties>
263+
<!-- There is no other way to deliver filename that was under processing -->
264+
<property name="violationSuppressXPath" value="//MethodDeclaration[@Name='process' and ../../..[@Image='Checker']]"/>
265+
</properties>
266+
</rule>
255267

256268
<rule ref="rulesets/java/strings.xml"/>
257269
<rule ref="rulesets/java/sunsecure.xml/MethodReturnsInternalArray">

config/suppressions.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
files="TokenTypes.java"
1010
lines="1"/>
1111

12+
<!-- There is no other way to deliver filename that was under processing -->
13+
<suppress checks="IllegalCatch"
14+
files="Checker.java"
15+
lines="279"/>
16+
1217
<!-- we can not change it as, Check name is part of API (used in configurations) -->
1318
<suppress checks="AbbreviationAsWordInName"
1419
files="JavaNCSSCheck.java"
@@ -95,7 +100,7 @@
95100

96101
<!-- Suppressions from PMD configuration-->
97102
<!-- validateCli is not reasonable to split as encapsulation of logic will be damaged -->
98-
<suppress checks="CyclomaticComplexity" files="Main\.java" lines="179"/>
103+
<suppress checks="CyclomaticComplexity" files="Main\.java" lines="169"/>
99104
<!-- JavadocMethodCheck, JavadocStyleCheck, JavadocUtils.getJavadocTags() - deprecated -->
100105
<suppress checks="CyclomaticComplexity" files="JavadocMethodCheck\.java"/>
101106
<suppress checks="CyclomaticComplexity" files="JavadocStyleCheck\.java"/>

src/main/java/com/puppycrawl/tools/checkstyle/Checker.java

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -252,28 +252,35 @@ public int process(List<File> files) throws CheckstyleException {
252252

253253
// Process each file
254254
for (final File file : files) {
255-
if (!CommonUtils.matchesFileExtension(file, fileExtensions)) {
256-
continue;
257-
}
258-
final String fileName = file.getAbsolutePath();
259-
fireFileStarted(fileName);
260-
final SortedSet<LocalizedMessage> fileMessages = Sets.newTreeSet();
261255
try {
262-
final FileText theText = new FileText(file.getAbsoluteFile(),
263-
charset);
264-
for (final FileSetCheck fsc : fileSetChecks) {
265-
fileMessages.addAll(fsc.process(file, theText));
256+
if (!CommonUtils.matchesFileExtension(file, fileExtensions)) {
257+
continue;
258+
}
259+
final String fileName = file.getAbsolutePath();
260+
fireFileStarted(fileName);
261+
final SortedSet<LocalizedMessage> fileMessages = Sets.newTreeSet();
262+
try {
263+
final FileText theText = new FileText(file.getAbsoluteFile(),
264+
charset);
265+
for (final FileSetCheck fsc : fileSetChecks) {
266+
fileMessages.addAll(fsc.process(file, theText));
267+
}
268+
}
269+
catch (final IOException ioe) {
270+
LOG.debug("IOException occurred.", ioe);
271+
fileMessages.add(new LocalizedMessage(0,
272+
Definitions.CHECKSTYLE_BUNDLE, "general.exception",
273+
new String[] {ioe.getMessage()}, null, getClass(),
274+
null));
266275
}
276+
fireErrors(fileName, fileMessages);
277+
fireFileFinished(fileName);
267278
}
268-
catch (final IOException ioe) {
269-
LOG.debug("IOException occurred.", ioe);
270-
fileMessages.add(new LocalizedMessage(0,
271-
Definitions.CHECKSTYLE_BUNDLE, "general.exception",
272-
new String[] {ioe.getMessage()}, null, getClass(),
273-
null));
279+
catch (Exception ex) {
280+
// We need to catch all exception to put a reason failure(file name) in exception
281+
throw new CheckstyleException("Exception was thrown while processing "
282+
+ file.getPath(), ex);
274283
}
275-
fireErrors(fileName, fileMessages);
276-
fireFileFinished(fileName);
277284
}
278285

279286
// Finish up

src/main/java/com/puppycrawl/tools/checkstyle/Main.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ private Main() {
8282
* is the number of errors found in all the files.
8383
* @param args the command line arguments.
8484
* @throws FileNotFoundException if there is a problem with files access
85+
* @noinspection CallToPrintStackTrace
8586
**/
8687
public static void main(String... args) throws FileNotFoundException {
8788
int errorCounter = 0;
@@ -131,7 +132,7 @@ public static void main(String... args) throws FileNotFoundException {
131132
catch (CheckstyleException e) {
132133
exitStatus = EXIT_WITH_CHECKSTYLE_EXCEPTION_CODE;
133134
errorCounter = 1;
134-
printMessageAndCause(e);
135+
e.printStackTrace();
135136
}
136137
finally {
137138
// return exit code base on validation of Checker
@@ -144,17 +145,6 @@ public static void main(String... args) throws FileNotFoundException {
144145
}
145146
}
146147

147-
/**
148-
* Prints message of exception to the first line and cause of exception to the second line.
149-
* @param exception to be written to console
150-
*/
151-
private static void printMessageAndCause(CheckstyleException exception) {
152-
System.out.println(exception.getMessage());
153-
if (exception.getCause() != null) {
154-
System.out.println("Cause: " + exception.getCause());
155-
}
156-
}
157-
158148
/**
159149
* Parses and executes Checkstyle based on passed arguments.
160150
* @param args

src/test/java/com/puppycrawl/tools/checkstyle/MainTest.java

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ private static String getPath(String filename) {
5959
return "src/test/resources/com/puppycrawl/tools/checkstyle/" + filename;
6060
}
6161

62+
private static String getNonCompilablePath(String filename) {
63+
return "src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/" + filename;
64+
}
65+
6266
private static String getFilePath(String filename) throws IOException {
6367
return new File(getPath(filename)).getCanonicalPath();
6468
}
@@ -143,11 +147,11 @@ public void testNonExistingConfigFile()
143147
exit.checkAssertionAfterwards(new Assertion() {
144148
@Override
145149
public void checkAssertion() {
146-
assertEquals(String.format(Locale.ROOT,
147-
"Unable to find: src/main/resources/non_existing_config.xml%n"
148-
+ "Checkstyle ends with 1 errors.%n"),
150+
assertEquals(String.format(Locale.ROOT, "Checkstyle ends with 1 errors.%n"),
149151
systemOut.getLog());
150-
assertEquals("", systemErr.getLog());
152+
final String cause = "com.puppycrawl.tools.checkstyle.api.CheckstyleException:"
153+
+ " Unable to find: src/main/resources/non_existing_config.xml";
154+
assertTrue(systemErr.getLog().startsWith(cause));
151155
}
152156
});
153157
Main.main("-c", "src/main/resources/non_existing_config.xml",
@@ -172,38 +176,18 @@ public void checkAssertion() {
172176
@Test
173177
public void testNonExistingClass() throws Exception {
174178
exit.expectSystemExitWithStatus(-2);
175-
final String cause = "Unable to instantiate 'NonExistingClass' class,"
176-
+ " it is also not possible to instantiate it as"
177-
+ " com.puppycrawl.tools.checkstyle.checks.annotation.NonExistingClass,"
178-
+ " com.puppycrawl.tools.checkstyle.checks.blocks.NonExistingClass,"
179-
+ " com.puppycrawl.tools.checkstyle.checks.coding.NonExistingClass,"
180-
+ " com.puppycrawl.tools.checkstyle.checks.design.NonExistingClass,"
181-
+ " com.puppycrawl.tools.checkstyle.checks.header.NonExistingClass,"
182-
+ " com.puppycrawl.tools.checkstyle.checks.imports.NonExistingClass,"
183-
+ " com.puppycrawl.tools.checkstyle.checks.indentation.NonExistingClass,"
184-
+ " com.puppycrawl.tools.checkstyle.checks.javadoc.NonExistingClass,"
185-
+ " com.puppycrawl.tools.checkstyle.checks.metrics.NonExistingClass,"
186-
+ " com.puppycrawl.tools.checkstyle.checks.modifier.NonExistingClass,"
187-
+ " com.puppycrawl.tools.checkstyle.checks.naming.NonExistingClass,"
188-
+ " com.puppycrawl.tools.checkstyle.checks.regexp.NonExistingClass,"
189-
+ " com.puppycrawl.tools.checkstyle.checks.sizes.NonExistingClass,"
190-
+ " com.puppycrawl.tools.checkstyle.checks.whitespace.NonExistingClass,"
191-
+ " com.puppycrawl.tools.checkstyle.checks.NonExistingClass,"
192-
+ " com.puppycrawl.tools.checkstyle.filters.NonExistingClass,"
193-
+ " com.puppycrawl.tools.checkstyle.NonExistingClass."
194-
+ " Please recheck that class name is specified as canonical name or read"
195-
+ " how to configure short name usage"
196-
+ " http://checkstyle.sourceforge.net/config.html#Packages."
197-
+ " Please also recheck that provided ClassLoader to Checker is configured correctly.";
198-
final String expectedExceptionMessage =
199-
String.format(Locale.ROOT, "cannot initialize module TreeWalker - %1$s%n"
200-
+ "Cause: com.puppycrawl.tools.checkstyle.api.CheckstyleException: %1$s%n"
201-
+ "Checkstyle ends with 1 errors.%n", cause);
202179
exit.checkAssertionAfterwards(new Assertion() {
203180
@Override
204181
public void checkAssertion() {
182+
final String expectedExceptionMessage =
183+
String.format(Locale.ROOT, "Checkstyle ends with 1 errors.%n");
205184
assertEquals(expectedExceptionMessage, systemOut.getLog());
206-
assertEquals("", systemErr.getLog());
185+
186+
final String cause = "com.puppycrawl.tools.checkstyle.api.CheckstyleException:"
187+
+ " cannot initialize module TreeWalker - "
188+
+ "Unable to instantiate 'NonExistingClass' class, "
189+
+ "it is also not possible to instantiate it as ";
190+
assertTrue(systemErr.getLog().startsWith(cause));
207191
}
208192
});
209193

@@ -434,16 +418,14 @@ public void testExistingIncorrectConfigFile()
434418
exit.checkAssertionAfterwards(new Assertion() {
435419
@Override
436420
public void checkAssertion() {
437-
assertTrue(systemOut.getLog().startsWith(String.format(Locale.ROOT,
438-
"unable to parse configuration stream"
439-
+ " - Content is not allowed in prolog.:7:1%n"
440-
+ "Cause: org.xml.sax.SAXParseException; systemId: file:")));
441-
assertTrue(systemOut.getLog().endsWith(String.format(Locale.ROOT,
442-
"com/puppycrawl/tools/checkstyle/config-Incorrect.xml;"
443-
+ " lineNumber: 7; columnNumber: 1; "
444-
+ "Content is not allowed in prolog.%n"
445-
+ "Checkstyle ends with 1 errors.%n")));
446-
assertEquals("", systemErr.getLog());
421+
final String output = String.format(Locale.ROOT,
422+
"Checkstyle ends with 1 errors.%n");
423+
assertEquals(output, systemOut.getLog());
424+
final String errorOuput = String.format(Locale.ROOT,
425+
"com.puppycrawl.tools.checkstyle.api."
426+
+ "CheckstyleException: unable to parse configuration stream"
427+
+ " - Content is not allowed in prolog.:7:1%n");
428+
assertTrue(systemErr.getLog().startsWith(errorOuput));
447429
}
448430
});
449431
Main.main("-c", getPath("config-Incorrect.xml"),
@@ -545,7 +527,7 @@ public void testExistingDirectoryWithViolations() throws Exception {
545527
});
546528

547529
Main.main("-c", getPath("config-filelength.xml"),
548-
getPath("checks/metrics"));
530+
getPath("checks/metrics"));
549531
}
550532

551533
@Test
@@ -577,4 +559,30 @@ public void testListFilesDirectoryWithNull() throws Exception {
577559
final List<File> result = (List<File>) method.invoke(null, fileMock);
578560
assertEquals(0, result.size());
579561
}
562+
563+
@Test
564+
public void testFileReferenceDuringException() throws Exception {
565+
exit.expectSystemExitWithStatus(-2);
566+
exit.checkAssertionAfterwards(new Assertion() {
567+
@Override
568+
public void checkAssertion() {
569+
final String expectedExceptionMessage =
570+
String.format(Locale.ROOT, "Starting audit...%n"
571+
+ "Checkstyle ends with 1 errors.%n");
572+
assertEquals(expectedExceptionMessage, systemOut.getLog());
573+
574+
final String exceptionFirstLine = String.format(Locale.ROOT,
575+
"com.puppycrawl.tools.checkstyle.api."
576+
+ "CheckstyleException: Exception was thrown while processing "
577+
+ new File(getNonCompilablePath("InputIncorrectClass.java")).getPath()
578+
+ "%n");
579+
assertTrue(systemErr.getLog().startsWith(exceptionFirstLine));
580+
}
581+
});
582+
583+
// We put xml as source to cause parse excepion
584+
Main.main("-c", getPath("config-classname.xml"),
585+
getNonCompilablePath("InputIncorrectClass.java"));
586+
}
587+
580588
}

src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractTypeAwareCheckTest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport;
3939
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
40+
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
4041
import com.puppycrawl.tools.checkstyle.checks.AbstractTypeAwareCheck;
4142

4243
@SuppressWarnings("deprecation")
@@ -164,10 +165,11 @@ public void testWithoutLogErrors() throws Exception {
164165
try {
165166
verify(config, getPath("InputLoadErrors.java"), expected);
166167
}
167-
catch (IllegalStateException ex) {
168+
catch (CheckstyleException ex) {
169+
final IllegalStateException cause = (IllegalStateException) ex.getCause();
168170
assertEquals("Unable to get"
169-
+ " class information for @throws tag 'InvalidExceptionName'.",
170-
ex.getMessage());
171+
+ " class information for @throws tag 'InvalidExceptionName'.",
172+
cause.getMessage());
171173
}
172174
}
173175

src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithNearbyCommentFilterTest.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,22 +240,39 @@ private static String[] removeSuppressed(String[] from, String... remove) {
240240
return coll.toArray(new String[coll.size()]);
241241
}
242242

243-
@Test(expected = ConversionException.class)
243+
@Test
244244
public void testInvalidInfluenceFormat() throws Exception {
245245
final DefaultConfiguration filterConfig =
246246
createFilterConfig(SuppressWithNearbyCommentFilter.class);
247247
filterConfig.addAttribute("influenceFormat", "a");
248248
final String[] suppressed = ArrayUtils.EMPTY_STRING_ARRAY;
249-
verifySuppressed(filterConfig, suppressed);
249+
250+
try {
251+
verifySuppressed(filterConfig, suppressed);
252+
}
253+
catch (CheckstyleException ex) {
254+
final ConversionException cause = (ConversionException) ex.getCause();
255+
assertEquals("unable to parse influence"
256+
+ " from 'SUPPRESS CHECKSTYLE MemberNameCheck' using a",
257+
cause.getMessage());
258+
}
250259
}
251260

252-
@Test(expected = ConversionException.class)
261+
@Test
253262
public void testInvalidCheckFormat() throws Exception {
254263
final DefaultConfiguration filterConfig =
255264
createFilterConfig(SuppressWithNearbyCommentFilter.class);
256265
filterConfig.addAttribute("checkFormat", "a[l");
257266
final String[] suppressed = ArrayUtils.EMPTY_STRING_ARRAY;
258-
verifySuppressed(filterConfig, suppressed);
267+
268+
try {
269+
verifySuppressed(filterConfig, suppressed);
270+
}
271+
catch (CheckstyleException ex) {
272+
final ConversionException cause = (ConversionException) ex.getCause();
273+
assertEquals("unable to parse expanded comment a[l",
274+
cause.getMessage());
275+
}
259276
}
260277

261278
@Test

src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilterTest.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,22 +254,39 @@ public void testToStringOfTagClass() {
254254
assertEquals("Tag[line=0; col=1; on=false; text='text']", tag.toString());
255255
}
256256

257-
@Test(expected = ConversionException.class)
257+
@Test
258258
public void testInvalidCheckFormat() throws Exception {
259259
final DefaultConfiguration filterConfig =
260260
createFilterConfig(SuppressionCommentFilter.class);
261261
filterConfig.addAttribute("checkFormat", "e[l");
262262
final String[] suppressed = ArrayUtils.EMPTY_STRING_ARRAY;
263-
verifySuppressed(filterConfig, suppressed);
263+
264+
try {
265+
verifySuppressed(filterConfig, suppressed);
266+
}
267+
catch (CheckstyleException ex) {
268+
final ConversionException cause = (ConversionException) ex.getCause();
269+
assertEquals("unable to parse expanded comment e[l",
270+
cause.getMessage());
271+
}
264272
}
265273

266-
@Test(expected = ConversionException.class)
274+
@Test
267275
public void testInvalidMessageFormat() throws Exception {
268276
final DefaultConfiguration filterConfig =
269277
createFilterConfig(SuppressionCommentFilter.class);
270278
filterConfig.addAttribute("messageFormat", "e[l");
271279
final String[] suppressed = ArrayUtils.EMPTY_STRING_ARRAY;
272-
verifySuppressed(filterConfig, suppressed);
280+
281+
try {
282+
verifySuppressed(filterConfig, suppressed);
283+
}
284+
catch (CheckstyleException ex) {
285+
final ConversionException cause = (ConversionException) ex.getCause();
286+
assertEquals("unable to parse expanded comment e[l",
287+
cause.getMessage());
288+
}
289+
273290
}
274291

275292
@Test
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!@#$^$^&%5

0 commit comments

Comments
 (0)