Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion src/main/java/edu/hm/hafner/analysis/parser/GccParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
static final String LINKER_ERROR = "Linker error";
private static final String GCC_WARNING_PATTERN = "^(?:\\s*(?:\\[.*\\]\\s*)?([^ ]*\\.[chpimxsola0-9]+):(?:(\\d*):"
+ "(?:\\d*:)*\\s*(?:(warning|error|note)\\s*:|\\s*(.*))|\\s*(undefined reference to.*))(.*)|.*ld:\\s*(.*-l("
+ ".*)))$";
+ ".*))|(?:In .+?:\\s*)?(cc1(?:plus)?):\\s*(warning|error|note):\\s*(.*))$";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this makes the parser more complex. Do you know if there are several different messages not picked up currently? I asked in JENKINS-73509, but maybe you have an answer already.


/**
* Creates a new instance of {@link GccParser}.
Expand All @@ -36,8 +36,39 @@
}

@Override
protected Optional<Issue> createIssue(final Matcher matcher, final LookaheadStream lookahead,

Check warning on line 39 in src/main/java/edu/hm/hafner/analysis/parser/GccParser.java

View check run for this annotation

ci.jenkins.io / PMD

CognitiveComplexity

NORMAL: The method 'createIssue(Matcher, LookaheadStream, IssueBuilder)' has a cognitive complexity of 20, current threshold is 15.
Raw output
Methods that are highly complex are difficult to read and more costly to maintain. If you include too much decisional logic within a single method, you make its behavior hard to understand and more difficult to modify. Cognitive complexity is a measure of how difficult it is for humans to read and understand a method. Code that contains a break in the control flow is more complex, whereas the use of language shorthands doesn't increase the level of complexity. Nested control flows can make a method more difficult to understand, with each additional nesting of the control flow leading to an increase in cognitive complexity. Information about Cognitive complexity can be found in the original paper here: <https://www.sonarsource.com/docs/CognitiveComplexity.pdf> By default, this rule reports methods with a complexity of 15 or more. Reported methods should be broken down into less complex components. <pre> <code> public class Foo { // Has a cognitive complexity of 0 public void createAccount() { Account account = new Account(&quot;PMD&quot;); // save account } // Has a cognitive complexity of 1 public Boolean setPhoneNumberIfNotExisting(Account a, String phone) { if (a.phone == null) { // +1 a.phone = phone; return true; } return false; } // Has a cognitive complexity of 4 public void updateContacts(List&lt;Contact&gt; contacts) { List&lt;Contact&gt; contactsToUpdate = new ArrayList&lt;Contact&gt;(); for (Contact contact : contacts) { // +1 if (contact.department.equals(&quot;Finance&quot;)) { // +2 (nesting = 1) contact.title = &quot;Finance Specialist&quot;; contactsToUpdate.add(contact); } else if (contact.department.equals(&quot;Sales&quot;)) { // +1 contact.title = &quot;Sales Specialist&quot;; contactsToUpdate.add(contact); } } // save contacts } } </code> </pre> <a href="https://docs.pmd-code.org/pmd-doc-7.17.0/pmd_rules_java_design.html#cognitivecomplexity"> See PMD documentation. </a>

Check warning on line 39 in src/main/java/edu/hm/hafner/analysis/parser/GccParser.java

View check run for this annotation

ci.jenkins.io / PMD

CyclomaticComplexity

NORMAL: The method 'createIssue(Matcher, LookaheadStream, IssueBuilder)' has a cyclomatic complexity of 14.
Raw output
The complexity of methods directly affects maintenance costs and readability. Concentrating too much decisional logic in a single method makes its behaviour hard to read and change. Cyclomatic complexity assesses the complexity of a method by counting the number of decision points in a method, plus one for the method entry. Decision points are places where the control flow jumps to another place in the program. As such, they include all control flow statements, such as `if`, `while`, `for`, and `case`. For more details on the calculation, see the documentation {% jdoc java::lang.java.metrics.JavaMetrics#CYCLO %}. Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote high complexity, and 11+ is very high complexity. By default, this rule reports methods with a complexity >= 10. Additionally, classes with many methods of moderate complexity get reported as well once the total of their methods' complexities reaches 80, even if none of the methods was directly reported. Reported methods should be broken down into several smaller methods. Reported classes should probably be broken down into subcomponents. <pre> <code> class Foo { void baseCyclo() { // Cyclo = 1 highCyclo(); } void highCyclo() { // Cyclo = 10: reported! int x = 0, y = 2; boolean a = false, b = true; if (a &amp;&amp; (y == 1 ? b : true)) { // +3 if (y == x) { // +1 while (true) { // +1 if (x++ &lt; 20) { // +1 break; // +1 } } } else if (y == t &amp;&amp; !d) { // +2 x = a ? y : x; // +1 } else { x = 2; } } } } </code> </pre> <a href="https://docs.pmd-code.org/pmd-doc-7.17.0/pmd_rules_java_design.html#cyclomaticcomplexity"> See PMD documentation. </a>
final IssueBuilder builder) {
// Handle cc1/cc1plus warnings
if (StringUtils.isNotBlank(matcher.group(9))) {
Severity priority;
if (equalsIgnoreCase(matcher.group(10), "warning")) {
priority = Severity.WARNING_NORMAL;
}
else if (equalsIgnoreCase(matcher.group(10), "error")) {
priority = Severity.WARNING_HIGH;
}
else if (equalsIgnoreCase(matcher.group(10), "note")) {
priority = Severity.WARNING_LOW;
}
else {
priority = Severity.WARNING_NORMAL;
}

// Handle multi-line messages for cc1/cc1plus warnings
var message = new StringBuilder(matcher.group(11));
while (lookahead.hasNext() && isCc1MessageContinuation(lookahead)) {
message.append(' ');
message.append(lookahead.next());
}

return builder.setFileName("")
.setLineStart(0)
.setCategory("GCC " + matcher.group(10))
.setMessage(StringEscapeUtils.escapeXml10(message.toString()))
.setSeverity(priority)
.buildOptional();
}

if (StringUtils.isNotBlank(matcher.group(7))) {
return builder.setFileName(matcher.group(8))
.setLineStart(0)
Expand Down Expand Up @@ -88,4 +119,30 @@
.setSeverity(priority)
.buildOptional();
}

/**
* Determines if the next line is a continuation of a cc1/cc1plus warning message.
*
* @param lookahead the lookahead stream
* @return true if the next line is a continuation
*/
private boolean isCc1MessageContinuation(final LookaheadStream lookahead) {
var peek = lookahead.peekNext();
if (peek.length() < 3) {

Check warning on line 131 in src/main/java/edu/hm/hafner/analysis/parser/GccParser.java

View check run for this annotation

ci.jenkins.io / PMD

AvoidLiteralsInIfCondition

NORMAL: Avoid using literals in if statements.
Raw output
Avoid using hard-coded literals in conditional statements. By declaring them as static variables or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. More exceptions can be defined with the property "ignoreMagicNumbers". The rule doesn't consider deeper expressions by default, but this can be enabled via the property `ignoreExpressions`. With this property set to false, if-conditions like `i == 1 + 5` are reported as well. Note that in that case, the property ignoreMagicNumbers is not taken into account, if there are multiple literals involved in such an expression. <pre> <code> private static final int MAX_NUMBER_OF_REQUESTS = 10; public void checkRequests() { if (i == 10) { // magic number, buried in a method doSomething(); } if (i == MAX_NUMBER_OF_REQUESTS) { // preferred approach doSomething(); } if (aString.indexOf(&#x27;.&#x27;) != -1) {} // magic number -1, by default ignored if (aString.indexOf(&#x27;.&#x27;) &gt;= 0) { } // alternative approach if (aDouble &gt; 0.0) {} // magic number 0.0 if (aDouble &gt;= Double.MIN_VALUE) {} // preferred approach // with rule property &quot;ignoreExpressions&quot; set to &quot;false&quot; if (i == pos + 5) {} // violation: magic number 5 within an (additive) expression if (i == pos + SUFFIX_LENGTH) {} // preferred approach if (i == 5 &amp;&amp; &quot;none&quot;.equals(aString)) {} // 2 violations: magic number 5 and literal &quot;none&quot; } </code> </pre> <a href="https://docs.pmd-code.org/pmd-doc-7.17.0/pmd_rules_java_errorprone.html#avoidliteralsinifcondition"> See PMD documentation. </a>
return false;
}
// Don't continue if the line starts with common patterns that indicate a new message
if (peek.charAt(0) == '/' || peek.charAt(0) == '[' || peek.charAt(0) == '<' || peek.charAt(0) == '=') {
return false;
}
if (peek.charAt(1) == ':') {

Check warning on line 138 in src/main/java/edu/hm/hafner/analysis/parser/GccParser.java

View check run for this annotation

ci.jenkins.io / PMD

AvoidLiteralsInIfCondition

NORMAL: Avoid using literals in if statements.
Raw output
Avoid using hard-coded literals in conditional statements. By declaring them as static variables or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. More exceptions can be defined with the property "ignoreMagicNumbers". The rule doesn't consider deeper expressions by default, but this can be enabled via the property `ignoreExpressions`. With this property set to false, if-conditions like `i == 1 + 5` are reported as well. Note that in that case, the property ignoreMagicNumbers is not taken into account, if there are multiple literals involved in such an expression. <pre> <code> private static final int MAX_NUMBER_OF_REQUESTS = 10; public void checkRequests() { if (i == 10) { // magic number, buried in a method doSomething(); } if (i == MAX_NUMBER_OF_REQUESTS) { // preferred approach doSomething(); } if (aString.indexOf(&#x27;.&#x27;) != -1) {} // magic number -1, by default ignored if (aString.indexOf(&#x27;.&#x27;) &gt;= 0) { } // alternative approach if (aDouble &gt; 0.0) {} // magic number 0.0 if (aDouble &gt;= Double.MIN_VALUE) {} // preferred approach // with rule property &quot;ignoreExpressions&quot; set to &quot;false&quot; if (i == pos + 5) {} // violation: magic number 5 within an (additive) expression if (i == pos + SUFFIX_LENGTH) {} // preferred approach if (i == 5 &amp;&amp; &quot;none&quot;.equals(aString)) {} // 2 violations: magic number 5 and literal &quot;none&quot; } </code> </pre> <a href="https://docs.pmd-code.org/pmd-doc-7.17.0/pmd_rules_java_errorprone.html#avoidliteralsinifcondition"> See PMD documentation. </a>
return false;
}
if (peek.charAt(2) == '/' || peek.charAt(0) == '\\') {
return false;
}

Check warning on line 143 in src/main/java/edu/hm/hafner/analysis/parser/GccParser.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>static boolean isMessageContinuation(final LookaheadStream lookahead) { var peek &#61; lookahead.peekNext(); if (peek.length() &lt; 3) { return false; } if (peek.charAt(0) &#61;&#61; &#39;/&#39; || peek.charAt(0) &#61;&#61; &#39;[&#39; || peek.charAt(0) &#61;&#61; &#39;&lt;&#39; || peek.charAt(0) &#61;&#61; &#39;&#61;&#39;) { return false; } if (peek.charAt(1) &#61;&#61; &#39;:&#39;) { return false; } if (peek.charAt(2) &#61;&#61; &#39;/&#39; || peek.charAt(0) &#61;&#61; &#39;\\&#39;) { return false; } return !StringUtils.containsAnyIgnoreCase(peek, &#34;arning&#34;, &#34;rror&#34;, &#34;make&#34;);</code></pre>
// Don't continue if the line contains patterns that indicate a new message
return !StringUtils.containsAnyIgnoreCase(peek, "arning", "rror", "make", "cc1", "cc1plus",
"In member function");
}
}
40 changes: 40 additions & 0 deletions src/test/java/edu/hm/hafner/analysis/parser/GccParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,46 @@ void ignoreDirectoriesFromOtherTools() {
assertThat(warnings).hasSize(8);
}

/**
* Parses cc1/cc1plus warnings that were previously ignored.
*
* @see <a href="https://issues.jenkins.io/browse/JENKINS-73509">Issue 73509</a>
*/
@Test
void issue73509() {
var warnings = parse("issue73509.txt");

assertThat(warnings).hasSize(3);

try (var softly = new SoftAssertions()) {
softly.assertThat(warnings.get(0))
.hasLineStart(0)
.hasLineEnd(0)
.hasMessage(
"&apos;void* _builtin_memset(void*, int, long unsigned int)&apos;: specified size 18446744073709551612 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]")
.hasFileName("-")
.hasCategory(GCC_WARNING)
.hasSeverity(Severity.WARNING_NORMAL);

softly.assertThat(warnings.get(1))
.hasLineStart(0)
.hasLineEnd(0)
.hasMessage(
"&apos;void* _builtin_memcpy(void*, const void*, long unsigned int)&apos;: specified size 18446744073709551612 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]")
.hasFileName("-")
.hasCategory(GCC_WARNING)
.hasSeverity(Severity.WARNING_NORMAL);

softly.assertThat(warnings.get(2))
.hasLineStart(451)
.hasLineEnd(451)
.hasMessage("`void yyunput(int, char*)&apos; defined but not used")
.hasFileName("testhist.l")
.hasCategory(GCC_WARNING)
.hasSeverity(Severity.WARNING_NORMAL);
}
}

@Override
protected GccParser createParser() {
return new GccParser();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
In member function 'void CInput::UpdateText(int, int, int)':
cc1plus: warning: 'void* _builtin_memset(void*, int, long unsigned int)': specified size 18446744073709551612
exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]

In member function 'void CInput::UpdateText(int, int, int)':
cc1: warning: 'void* _builtin_memcpy(void*, const void*, long unsigned int)': specified size 18446744073709551612
exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]

testhist.l:451: warning: `void yyunput(int, char*)' defined but not used
Comment on lines +1 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this output generated by an actual compiler call? Or did you just copy the text from the issue?

Copy link
Author

@akash-manna-sky akash-manna-sky Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
As it was there in JIRA, I didn't validate it against raw compiler logs.
Please let me know if there’s anything I need to update or improve to help move it forward.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without more details and input from the author of the issue it does not make sense to continue here.

Loading