Skip to content

Commit

Permalink
support new animalsniffer messages for field violations (#25);
Browse files Browse the repository at this point in the history
always put line number in file report, even if it wasn't declared (consistency with console reporting)
  • Loading branch information
xvik committed Sep 5, 2022
1 parent f568b54 commit a152c8a
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,6 @@
* Support animalsniffer messages for field violations (#25)
* Always put line number in file report, even if it wasn't declared (consistency with console reporting)

### 1.6.0 (2022-08-20)
* Update animalsniffer 1.20 -> 1.22 (java 9 support)
* Fix configuration cache support for check tasks (#26)
Expand Down
Expand Up @@ -13,6 +13,7 @@ class ReportMessage {
String signature
String source
String line
String field
String code
boolean parseFail
}
Expand Up @@ -15,10 +15,14 @@ class FormatUtils {
private static final String LINE_SEP = ':'
private static final String NL = String.format('%n')
private static final String UND_REF = 'Undefined reference:'
private static final String FIELD_REF = ' Field '

/**
* Parse animasniffer ant task error.
* Error format: <code>file_path:lineNum: Undefined reference: type source line</code>
* <p>
* In case of fields, it is impossible (for animalsniffer) to detect source line, instead, it would add field name
* in the message: <code>file_path Field 'name': Undefined reference: type source line</code>
*
* @param message animalsniffer error
* @param roots source directories (roots)
Expand All @@ -30,7 +34,20 @@ class FormatUtils {
// try to look for first space (this will lead to wrong result if file path contain space)
msgStartIdx = message.indexOf(' ')
}
String vclass = message[0..(msgStartIdx - 1)].trim()
String position = message[0..(msgStartIdx - 1)].trim()
int fieldIdx = position.indexOf(FIELD_REF)
String vclass
String field = null
if (fieldIdx > 0) {
// -2 to cut off trailing ':'
vclass = position[0..(fieldIdx - 1)].trim()
field = position[fieldIdx..-2].trim()
// use "field" instead of "Field"
field = field.uncapitalize()
} else {
vclass = position
}

if (vclass.endsWith(LINE_SEP)) {
// case when line number is not specified
vclass = vclass[0..(vclass.length() - 2)]
Expand All @@ -42,7 +59,7 @@ class FormatUtils {
}
String code = message[msgStartIdx..-1]
code = code.replace(UND_REF, '').trim()
return new ReportMessage(source: vclass, line: line, code: code)
return new ReportMessage(source: vclass, line: line, field: field, code: code)
}

/**
Expand All @@ -60,9 +77,10 @@ class FormatUtils {
idx = 0
}
String sig = showSignature ? " (${msg.signature})" : ''
String srcLine = msg.line ?
"${msg.source[0..(idx - 1)]}:${msg.line}" :
"${msg.source[0..(idx - 1)]}"
String srcLine = "${msg.source[0..(idx - 1)]}:${msg.line ? msg.line : 1}"
if (msg.field) {
srcLine += ' (' + msg.field + ')'
}
return "$srcLine Undefined reference$sig: ${msg.code}"
}

Expand All @@ -85,6 +103,9 @@ class FormatUtils {
String srcLine = clsIdx > 0 ?
"${msg.source[0..clsIdx]}(${msg.source[(clsIdx + 1)..-1]}:${msg.line ?: 1})" :
"${msg.source}${msg.line ? LINE_SEP + msg.line : ''}"
if (msg.field) {
srcLine += " $msg.field"
}
return "[Undefined reference$sig] $srcLine$NL" +
" >> ${msg.code}$NL"
}
Expand Down
Expand Up @@ -78,6 +78,25 @@ class ErrorFormatTest extends Specification {
!msg.parseFail
msg.code == 'java.util.function.Consumer'
FormatUtils.formatForConsole(msg, false).replaceAll('\r', '') == '[Undefined reference] retrolambda.(Sample.java:1)\n >> java.util.function.Consumer\n'
FormatUtils.formatForFile(msg, false) == 'retrolambda.Sample Undefined reference: java.util.function.Consumer'
FormatUtils.formatForFile(msg, false) == 'retrolambda.Sample:1 Undefined reference: java.util.function.Consumer'
}

def "Check field reference support"() {

Set<File> roots = [new File("/opt/foo") ]

when: "line with field"
ReportMessage msg = FormatUtils.parse(
'/opt/foo/invalid/Sample.java Field \'field\': Undefined reference: java.nio.file.Path'
, roots)
then: "parsed"
msg.source == 'invalid.Sample.java'
msg.line == null
msg.field == 'field \'field\''
msg.code == 'java.nio.file.Path'

then: "formatting"
FormatUtils.formatForFile(msg, false) == "invalid.Sample:1 (field 'field') Undefined reference: java.nio.file.Path"
FormatUtils.formatForConsole(msg, false) == "[Undefined reference] invalid.(Sample.java:1) field 'field'\n >> java.nio.file.Path\n"
}
}
Expand Up @@ -56,6 +56,53 @@ class FailKitTest extends AbstractKitTest {
]
}

def "Check field type violation"() {
setup:
build """
plugins {
id 'java'
id 'ru.vyarus.animalsniffer'
}
animalsniffer {
ignoreFailures = true
}
repositories { mavenCentral()}
dependencies {
signature 'org.codehaus.mojo.signature:java16-sun:1.0@signature'
implementation 'org.slf4j:slf4j-api:1.7.25'
}
"""
fileFromClasspath('src/main/java/invalid/Sample.java', '/ru/vyarus/gradle/plugin/animalsniffer/java/field/Sample.java')
// debug()

when: "run task"
BuildResult result = run('check')

then: "task successful"
result.task(':check').outcome == TaskOutcome.SUCCESS

then: "found 2 violations"
result.output.contains("2 AnimalSniffer violations were found in 1 files")
result.output.replaceAll('\r', '').contains(
"""[Undefined reference] invalid.(Sample.java:1)
>> java.nio.file.Path
[Undefined reference] invalid.(Sample.java:13)
>> int Boolean.compare(boolean, boolean)
""")

then: "report correct"
File file = file('/build/reports/animalsniffer/main.text')
file.exists()
file.readLines() == [
"invalid.Sample:1 Undefined reference: java.nio.file.Path",
"invalid.Sample:13 Undefined reference: int Boolean.compare(boolean, boolean)"
]
}


def "Check multiple signatures"() {
setup:
Expand Down
Expand Up @@ -27,12 +27,12 @@ class MsgFormatTest extends Specification {
when: "no line"
res = FormatUtils.formatForFile(new ReportMessage(source: "some.Sample.java", code: 'bla'), false)
then: "correct"
res == 'some.Sample Undefined reference: bla'
res == 'some.Sample:1 Undefined reference: bla'

when: "incorrect source"
res = FormatUtils.formatForFile(new ReportMessage(source: "failed source", code: 'bla'), false)
then: "correct"
res == 'failed source Undefined reference: bla'
res == 'failed source:1 Undefined reference: bla'

when: "failed parse"
res = FormatUtils.formatForFile(new ReportMessage(parseFail: true, code: 'bla bla'), false)
Expand Down
@@ -0,0 +1,15 @@
package invalid;

import org.slf4j.LoggerFactory;

import java.nio.file.Path;

public class Sample {

private Path field;

public static void main(String[] args) {
// method added in 1.7
Boolean.compare(true, true);
}
}

0 comments on commit a152c8a

Please sign in to comment.