You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2026/04/21 06:13:12 UTC
(groovy) 01/34: GROOVY-9057 — non-zero exit code on errors
This is an automated email from the ASF dual-hosted git repository.
paulk-asert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit e3e5648837d731c972a1111ac165182aa926c82b
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Apr 20 07:12:24 2026 +1000
GROOVY-9057 — non-zero exit code on errors
---
.../java/org/codehaus/groovy/ant/Groovydoc.java | 6 ++++-
.../codehaus/groovy/tools/groovydoc/Main.groovy | 18 ++++++++++++---
.../groovy/tools/groovydoc/GroovyDocTool.java | 7 ++++++
.../tools/groovydoc/GroovyRootDocBuilder.java | 6 +++++
.../groovy/tools/groovydoc/GroovyDocToolTest.java | 10 +++++++++
.../src/test/resources/broken/BrokenSyntax.groovy | 26 ++++++++++++++++++++++
6 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovydoc.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovydoc.java
index b23f4b0c95..ec4b53fb90 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovydoc.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovydoc.java
@@ -488,7 +488,11 @@ public class Groovydoc extends Task {
FileOutputTool output = new FileOutputTool();
htmlTool.renderToOutput(output, destDir.getCanonicalPath()); // TODO push destDir through APIs?
} catch (Exception e) {
- e.printStackTrace();
+ throw new BuildException("Groovydoc generation failed: " + e.getMessage(), e);
+ }
+ int errorCount = htmlTool.getErrorCount();
+ if (errorCount > 0) {
+ throw new BuildException("Groovydoc failed to parse " + errorCount + " source file(s).");
}
// try to override the default stylesheet with custom specified one if needed
if (styleSheetFile != null) {
diff --git a/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy b/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
index 1ccc2c024b..a18ddb5555 100644
--- a/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
+++ b/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
@@ -148,7 +148,7 @@ class Main {
} else if (scopeCount > 1) {
System.err.println "groovydoc: Error - More than one of -public, -private, -package, or -protected specified."
cli.usage()
- return
+ System.exit(1)
}
windowTitle = options.windowtitle ?: ''
@@ -181,12 +181,23 @@ class Main {
if (!remainingArgs) {
System.err.println "groovydoc: Error - No packages or classes specified."
cli.usage()
+ System.exit(1)
+ }
+ int errorCount
+ try {
+ errorCount = execute()
+ } catch (Throwable t) {
+ t.printStackTrace(System.err)
+ System.exit(1)
return
}
- execute()
+ if (errorCount > 0) {
+ System.err.println "groovydoc: Error - $errorCount source file(s) failed to parse."
+ System.exit(1)
+ }
}
- static void execute() {
+ static int execute() {
Properties properties = new Properties()
properties.put("windowTitle", windowTitle)
properties.put("docTitle", docTitle)
@@ -232,6 +243,7 @@ class Main {
println "Warning: Unable to copy specified stylesheet '" + styleSheetFile.absolutePath + "'. Using default stylesheet instead. Due to: " + e.message
}
}
+ return htmlTool.errorCount
}
static collectSourceFileNames(List<String> remainingArgs, String[] sourceDirs, List<String> exclusions) {
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java
index bf8f40b120..77b2417b4c 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java
@@ -139,6 +139,13 @@ public class GroovyDocTool {
return rootDocBuilder.getRootDoc();
}
+ /**
+ * @return the number of source files that could not be parsed
+ */
+ public int getErrorCount() {
+ return rootDocBuilder.getErrorCount();
+ }
+
public void renderToOutput(OutputTool output, String destdir) throws Exception {
// expect just one scope to be set on the way in but now also set higher levels of visibility
if ("true".equals(properties.getProperty("privateScope"))) properties.setProperty("packageScope", "true");
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyRootDocBuilder.java b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyRootDocBuilder.java
index 1c36ecee37..a3090b0251 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyRootDocBuilder.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyRootDocBuilder.java
@@ -52,6 +52,7 @@ public class GroovyRootDocBuilder {
private final String[] sourcepaths;
private final SimpleGroovyRootDoc rootDoc;
private final Properties properties;
+ private int errorCount;
@Deprecated
public GroovyRootDocBuilder(GroovyDocTool tool, String[] sourcepaths, List<LinkArgument> links, Properties properties) {
@@ -142,12 +143,17 @@ public class GroovyRootDocBuilder {
packageDoc.putAll(classDocs);
rootDoc.put(packagePath, packageDoc);
} catch (RuntimeException e) {
+ errorCount++;
e.printStackTrace(System.err);
log.error("ignored due to parsing exception: " + filename + " [" + e.getMessage() + "]");
log.debug("ignored due to parsing exception: " + filename + " [" + e.getMessage() + "]", e);
}
}
+ public int getErrorCount() {
+ return errorCount;
+ }
+
/* package private */ void processPackageInfo(String src, String filename, SimpleGroovyPackageDoc packageDoc) {
String relPath = packageDoc.getRelativeRootPath();
String description = calcThenSetPackageDescription(src, filename, relPath);
diff --git a/subprojects/groovy-groovydoc/src/test/groovy/org/codehaus/groovy/tools/groovydoc/GroovyDocToolTest.java b/subprojects/groovy-groovydoc/src/test/groovy/org/codehaus/groovy/tools/groovydoc/GroovyDocToolTest.java
index 3033c0142c..6e9b3b0ba2 100644
--- a/subprojects/groovy-groovydoc/src/test/groovy/org/codehaus/groovy/tools/groovydoc/GroovyDocToolTest.java
+++ b/subprojects/groovy-groovydoc/src/test/groovy/org/codehaus/groovy/tools/groovydoc/GroovyDocToolTest.java
@@ -94,6 +94,16 @@ public class GroovyDocToolTest extends GroovyTestCase {
);
}
+ // GROOVY-9057
+ public void testParseErrorIsTrackedInErrorCount() throws Exception {
+ assertEquals("Initial error count should be zero", 0, xmlToolForTests.getErrorCount());
+ List<String> srcList = new ArrayList<>();
+ srcList.add("broken/BrokenSyntax.groovy");
+ xmlToolForTests.add(srcList);
+ assertTrue("Expected errorCount > 0 after parsing malformed source, was "
+ + xmlToolForTests.getErrorCount(), xmlToolForTests.getErrorCount() > 0);
+ }
+
public void testPlainGroovyDocTool() throws Exception {
List<String> srcList = new ArrayList<>();
srcList.add("org/codehaus/groovy/tools/groovydoc/GroovyDocToolTest.java");
diff --git a/subprojects/groovy-groovydoc/src/test/resources/broken/BrokenSyntax.groovy b/subprojects/groovy-groovydoc/src/test/resources/broken/BrokenSyntax.groovy
new file mode 100644
index 0000000000..9f2a0c0bfa
--- /dev/null
+++ b/subprojects/groovy-groovydoc/src/test/resources/broken/BrokenSyntax.groovy
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// Intentionally malformed source used by
+// org.codehaus.groovy.tools.groovydoc.GroovyDocToolTest.testParseErrorIsTrackedInErrorCount
+// (GROOVY-9057) to verify that parse failures bump the error count.
+package broken
+
+class BrokenSyntax {
+ def foo(
+}