Documentation
¶
Index ¶
- type CheckStyleError
- type CheckStyleFile
- type CheckStyleParser
- type CheckStyleResult
- type DiffParser
- type ErrorformatParser
- type Option
- type Parser
- type RDJSONLParser
- type RDJSONParser
- type SarifArtifactLocation
- type SarifJson
- type SarifOriginalURI
- type SarifParser
- type SarifRegion
- type SarifRule
- type SarifText
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CheckStyleError ¶
type CheckStyleError struct {
Column int `xml:"column,attr,omitempty"`
Line int `xml:"line,attr"`
Message string `xml:"message,attr"`
Severity string `xml:"severity,attr,omitempty"`
Source string `xml:"source,attr,omitempty"`
}
CheckStyleError represents <error line="1" column="10" severity="error" message="msg" source="src" />
type CheckStyleFile ¶
type CheckStyleFile struct {
Name string `xml:"name,attr"`
Errors []*CheckStyleError `xml:"error"`
}
CheckStyleFile represents <file name="fname"><error ... />...</file>
type CheckStyleParser ¶
type CheckStyleParser struct{}
CheckStyleParser is checkstyle parser.
Example ¶
const sample = `<?xml version="1.0" encoding="utf-8"?><checkstyle version="4.3"><file name="/path/to/file"><error line="1" column="10" severity="error" message="'addOne' is defined but never used. (no-unused-vars)" source="eslint.rules.no-unused-vars" /><error line="2" column="9" severity="error" message="Use the isNaN function to compare with NaN. (use-isnan)" source="eslint.rules.use-isnan" /><error line="3" column="16" severity="error" message="Unexpected space before unary operator '++'. (space-unary-ops)" source="eslint.rules.space-unary-ops" /><error line="3" column="20" severity="warning" message="Missing semicolon. (semi)" source="eslint.rules.semi" /><error line="4" column="12" severity="warning" message="Unnecessary 'else' after 'return'. (no-else-return)" source="eslint.rules.no-else-return" /><error line="5" column="7" severity="warning" message="Expected indentation of 8 spaces but found 6. (indent)" source="eslint.rules.indent" /><error line="5" column="7" severity="error" message="Expected a return value. (consistent-return)" source="eslint.rules.consistent-return" /><error line="5" column="13" severity="warning" message="Missing semicolon. (semi)" source="eslint.rules.semi" /><error line="7" column="2" severity="error" message="Unnecessary semicolon. (no-extra-semi)" source="eslint.rules.no-extra-semi" /></file></checkstyle>`
p := NewCheckStyleParser()
diagnostics, err := p.Parse(strings.NewReader(sample))
if err != nil {
panic(err)
}
for _, d := range diagnostics {
rdjson, _ := protojson.MarshalOptions{Indent: " "}.Marshal(d)
var out bytes.Buffer
json.Indent(&out, rdjson, "", " ")
fmt.Println(out.String())
}
Output: { "message": "'addOne' is defined but never used. (no-unused-vars)", "location": { "path": "/path/to/file", "range": { "start": { "line": 1, "column": 10 } } }, "severity": "ERROR", "code": { "value": "eslint.rules.no-unused-vars" }, "originalOutput": "/path/to/file:1:10: error: 'addOne' is defined but never used. (no-unused-vars) (eslint.rules.no-unused-vars)" } { "message": "Use the isNaN function to compare with NaN. (use-isnan)", "location": { "path": "/path/to/file", "range": { "start": { "line": 2, "column": 9 } } }, "severity": "ERROR", "code": { "value": "eslint.rules.use-isnan" }, "originalOutput": "/path/to/file:2:9: error: Use the isNaN function to compare with NaN. (use-isnan) (eslint.rules.use-isnan)" } { "message": "Unexpected space before unary operator '++'. (space-unary-ops)", "location": { "path": "/path/to/file", "range": { "start": { "line": 3, "column": 16 } } }, "severity": "ERROR", "code": { "value": "eslint.rules.space-unary-ops" }, "originalOutput": "/path/to/file:3:16: error: Unexpected space before unary operator '++'. (space-unary-ops) (eslint.rules.space-unary-ops)" } { "message": "Missing semicolon. (semi)", "location": { "path": "/path/to/file", "range": { "start": { "line": 3, "column": 20 } } }, "severity": "WARNING", "code": { "value": "eslint.rules.semi" }, "originalOutput": "/path/to/file:3:20: warning: Missing semicolon. (semi) (eslint.rules.semi)" } { "message": "Unnecessary 'else' after 'return'. (no-else-return)", "location": { "path": "/path/to/file", "range": { "start": { "line": 4, "column": 12 } } }, "severity": "WARNING", "code": { "value": "eslint.rules.no-else-return" }, "originalOutput": "/path/to/file:4:12: warning: Unnecessary 'else' after 'return'. (no-else-return) (eslint.rules.no-else-return)" } { "message": "Expected indentation of 8 spaces but found 6. (indent)", "location": { "path": "/path/to/file", "range": { "start": { "line": 5, "column": 7 } } }, "severity": "WARNING", "code": { "value": "eslint.rules.indent" }, "originalOutput": "/path/to/file:5:7: warning: Expected indentation of 8 spaces but found 6. (indent) (eslint.rules.indent)" } { "message": "Expected a return value. (consistent-return)", "location": { "path": "/path/to/file", "range": { "start": { "line": 5, "column": 7 } } }, "severity": "ERROR", "code": { "value": "eslint.rules.consistent-return" }, "originalOutput": "/path/to/file:5:7: error: Expected a return value. (consistent-return) (eslint.rules.consistent-return)" } { "message": "Missing semicolon. (semi)", "location": { "path": "/path/to/file", "range": { "start": { "line": 5, "column": 13 } } }, "severity": "WARNING", "code": { "value": "eslint.rules.semi" }, "originalOutput": "/path/to/file:5:13: warning: Missing semicolon. (semi) (eslint.rules.semi)" } { "message": "Unnecessary semicolon. (no-extra-semi)", "location": { "path": "/path/to/file", "range": { "start": { "line": 7, "column": 2 } } }, "severity": "ERROR", "code": { "value": "eslint.rules.no-extra-semi" }, "originalOutput": "/path/to/file:7:2: error: Unnecessary semicolon. (no-extra-semi) (eslint.rules.no-extra-semi)" }
func (*CheckStyleParser) Parse ¶
func (p *CheckStyleParser) Parse(r io.Reader) ([]*rdf.Diagnostic, error)
type CheckStyleResult ¶
type CheckStyleResult struct {
XMLName xml.Name `xml:"checkstyle"`
Version string `xml:"version,attr"`
Files []*CheckStyleFile `xml:"file,omitempty"`
}
CheckStyleResult represents checkstyle XML result. <?xml version="1.0" encoding="utf-8"?><checkstyle version="4.3"><file ...></file>...</checkstyle>
References:
type DiffParser ¶
type DiffParser struct {
// contains filtered or unexported fields
}
DiffParser is a unified diff parser.
Example ¶
const sample = `diff --git a/gofmt.go b/gofmt.go
--- a/gofmt.go 2020-07-26 08:01:09.260800318 +0000
+++ b/gofmt.go 2020-07-26 08:01:09.260800318 +0000
@@ -1,6 +1,6 @@
package testdata
-func fmt () {
+func fmt() {
// test
// test line
// test line
@@ -10,11 +10,11 @@
// test line
// test line
-println(
- "hello, gofmt test" )
-//comment
+ println(
+ "hello, gofmt test")
+ //comment
}
+type s struct{ A int }
-type s struct { A int }
func (s s) String() { return "s" }
`
const strip = 1
p := NewDiffParser(strip)
diagnostics, err := p.Parse(strings.NewReader(sample))
if err != nil {
panic(err)
}
for _, d := range diagnostics {
rdjson, _ := protojson.MarshalOptions{Indent: " "}.Marshal(d)
var out bytes.Buffer
json.Indent(&out, rdjson, "", " ")
fmt.Println(out.String())
}
Output: { "location": { "path": "gofmt.go", "range": { "start": { "line": 3 }, "end": { "line": 3 } } }, "suggestions": [ { "range": { "start": { "line": 3 }, "end": { "line": 3 } }, "text": "func fmt() {" } ], "originalOutput": "gofmt.go:3:-func fmt () {\ngofmt.go:3:+func fmt() {" } { "location": { "path": "gofmt.go", "range": { "start": { "line": 13 }, "end": { "line": 15 } } }, "suggestions": [ { "range": { "start": { "line": 13 }, "end": { "line": 15 } }, "text": "\tprintln(\n\t\t\"hello, gofmt test\")\n\t//comment" } ], "originalOutput": "gofmt.go:13:-println(\ngofmt.go:14:-\t\t\"hello, gofmt test\" )\ngofmt.go:15:-//comment\ngofmt.go:13:+\tprintln(\ngofmt.go:14:+\t\t\"hello, gofmt test\")\ngofmt.go:15:+\t//comment" } { "location": { "path": "gofmt.go", "range": { "start": { "line": 18, "column": 1 }, "end": { "line": 18, "column": 1 } } }, "suggestions": [ { "range": { "start": { "line": 18, "column": 1 }, "end": { "line": 18, "column": 1 } }, "text": "type s struct{ A int }\n" } ], "originalOutput": "gofmt.go:18:+type s struct{ A int }" } { "location": { "path": "gofmt.go", "range": { "start": { "line": 19 }, "end": { "line": 19 } } }, "suggestions": [ { "range": { "start": { "line": 19 }, "end": { "line": 19 } } } ], "originalOutput": "gofmt.go:19:-type s struct { A int }" }
func NewDiffParser ¶
func NewDiffParser(strip int) *DiffParser
NewDiffParser creates a new DiffParser.
func (*DiffParser) Parse ¶
func (p *DiffParser) Parse(r io.Reader) ([]*rdf.Diagnostic, error)
Parse parses input as unified diff format and return it as diagnostics.
type ErrorformatParser ¶
type ErrorformatParser struct {
// contains filtered or unexported fields
}
ErrorformatParser is errorformat parser.
Example ¶
const sample = `/path/to/file1.txt:1:14: [E][RULE:14] message 1
/path/to/file2.txt:2:14: [N][RULE:7] message 2`
p, err := NewErrorformatParserString([]string{`%f:%l:%c: [%t][RULE:%n] %m`})
if err != nil {
panic(err)
}
diagnostics, err := p.Parse(strings.NewReader(sample))
if err != nil {
panic(err)
}
for _, d := range diagnostics {
rdjson, _ := protojson.MarshalOptions{Indent: " "}.Marshal(d)
var out bytes.Buffer
json.Indent(&out, rdjson, "", " ")
fmt.Println(out.String())
}
Output: { "message": "message 1", "location": { "path": "/path/to/file1.txt", "range": { "start": { "line": 1, "column": 14 } } }, "severity": "ERROR", "code": { "value": "14" }, "originalOutput": "/path/to/file1.txt:1:14: [E][RULE:14] message 1" } { "message": "message 2", "location": { "path": "/path/to/file2.txt", "range": { "start": { "line": 2, "column": 14 } } }, "severity": "INFO", "code": { "value": "7" }, "originalOutput": "/path/to/file2.txt:2:14: [N][RULE:7] message 2" }
func NewErrorformatParser ¶
func NewErrorformatParser(efm *errorformat.Errorformat) *ErrorformatParser
NewErrorformatParser returns a new ErrorformatParser.
func NewErrorformatParserString ¶
func NewErrorformatParserString(efms []string) (*ErrorformatParser, error)
NewErrorformatParserString returns a new ErrorformatParser from errorformat in string representation.
func (*ErrorformatParser) Parse ¶
func (p *ErrorformatParser) Parse(r io.Reader) ([]*rdf.Diagnostic, error)
type Option ¶
Option represents option to create Parser. Either FormatName or Errorformat should be specified.
type Parser ¶
type Parser interface {
Parse(r io.Reader) ([]*rdf.Diagnostic, error)
}
Parser is an interface which parses compilers, linters, or any tools results.
func NewCheckStyleParser ¶
func NewCheckStyleParser() Parser
NewCheckStyleParser returns a new CheckStyleParser.
type RDJSONLParser ¶
type RDJSONLParser struct{}
RDJSONLParser is parser for rdjsonl format.
func NewRDJSONLParser ¶
func NewRDJSONLParser() *RDJSONLParser
NewRDJSONLParser returns a new RDJSONParser.
func (*RDJSONLParser) Parse ¶
func (p *RDJSONLParser) Parse(r io.Reader) ([]*rdf.Diagnostic, error)
Parse parses rdjson (JSONL of Diagnostic).
type RDJSONParser ¶
type RDJSONParser struct{}
RDJSONParser is parser for rdjsonl format.
Example ¶
const sample = `
{
"source": {
"name": "linter-name",
"url": "https://github.com/khulnasoft#linter-name"
},
"severity": "INFO",
"diagnostics": [
{
"source": {
"name": "deadcode"
},
"message": "'unused' is unused",
"location": {
"path": "testdata/main.go",
"range": {
"start": {
"line": 18,
"column": 6
}
}
}
},
{
"message": "printf: Sprintf format %d reads arg #1, but call has 0 args",
"location": {
"path": "testdata/main.go",
"range": {
"start": {
"line": 13,
"column": 2
}
}
}
},
{
"source": {
"name": "severity-test"
},
"message": "severity test (string)",
"location": {
"path": "testdata/main.go",
"range": {
"start": {
"line": 24,
"column": 6
}
}
},
"severity": "WARNING"
},
{
"source": {
"name": "severity-test"
},
"message": "severity test (number)",
"location": {
"path": "testdata/main.go",
"range": {
"start": {
"line": 24,
"column": 6
}
}
},
"severity": 1
}
]
}`
p := NewRDJSONParser()
diagnostics, err := p.Parse(strings.NewReader(sample))
if err != nil {
panic(err)
}
for _, d := range diagnostics {
d.OriginalOutput = "" // Skip for testing as it's not deterministic.
rdjson, _ := protojson.MarshalOptions{Indent: " "}.Marshal(d)
var out bytes.Buffer
json.Indent(&out, rdjson, "", " ")
fmt.Println(out.String())
}
Output: { "message": "'unused' is unused", "location": { "path": "testdata/main.go", "range": { "start": { "line": 18, "column": 6 } } }, "severity": "INFO", "source": { "name": "deadcode" } } { "message": "printf: Sprintf format %d reads arg #1, but call has 0 args", "location": { "path": "testdata/main.go", "range": { "start": { "line": 13, "column": 2 } } }, "severity": "INFO", "source": { "name": "linter-name", "url": "https://github.com/khulnasoft#linter-name" } } { "message": "severity test (string)", "location": { "path": "testdata/main.go", "range": { "start": { "line": 24, "column": 6 } } }, "severity": "WARNING", "source": { "name": "severity-test" } } { "message": "severity test (number)", "location": { "path": "testdata/main.go", "range": { "start": { "line": 24, "column": 6 } } }, "severity": "ERROR", "source": { "name": "severity-test" } }
func NewRDJSONParser ¶
func NewRDJSONParser() *RDJSONParser
NewRDJSONParser returns a new RDJSONParser.
func (*RDJSONParser) Parse ¶
func (p *RDJSONParser) Parse(r io.Reader) ([]*rdf.Diagnostic, error)
Parse parses rdjson (JSON of DiagnosticResult).
type SarifArtifactLocation ¶
type SarifArtifactLocation struct {
URI string `json:"uri"`
URIBaseID string `json:"uriBaseId"`
Index int `json:"index"`
}
func (*SarifArtifactLocation) GetPath ¶
func (l *SarifArtifactLocation) GetPath( baseURIs map[string]SarifOriginalURI, basedir string, ) (string, error)
type SarifJson ¶
type SarifJson struct {
Runs []struct {
OriginalURIBaseIds map[string]SarifOriginalURI `json:"originalUriBaseIds"`
Results []struct {
Level string `json:"level"`
Locations []struct {
PhysicalLocation struct {
ArtifactLocation SarifArtifactLocation `json:"artifactLocation"`
Region SarifRegion `json:"region"`
} `json:"physicalLocation"`
} `json:"locations"`
Message SarifText `json:"message"`
RuleID string `json:"ruleId"`
Fixes []struct {
Description SarifText `json:"description"`
ArtifactChanges []struct {
ArtifactLocation SarifArtifactLocation `json:"artifactLocation"`
Replacements []struct {
DeletedRegion SarifRegion `json:"deletedRegion"`
InsertedContent struct {
Text string `json:"text"`
} `json:"insertedContent"`
} `json:"replacements"`
} `json:"artifactChanges"`
} `json:"fixes"`
} `json:"results"`
Tool struct {
Driver struct {
FullName string `json:"fullName"`
InformationURI string `json:"informationUri"`
Name string `json:"name"`
Rules []SarifRule `json:"rules"`
} `json:"driver"`
} `json:"tool"`
} `json:"runs"`
}
SARIF JSON Format
References:
type SarifOriginalURI ¶
type SarifOriginalURI struct {
URI string `json:"uri"`
}
type SarifParser ¶
type SarifParser struct{}
SarifParser is sarif parser.
func (*SarifParser) Parse ¶
func (p *SarifParser) Parse(r io.Reader) ([]*rdf.Diagnostic, error)
type SarifRegion ¶
type SarifRegion struct {
StartLine *int `json:"startLine"`
StartColumn *int `json:"startColumn"`
EndLine *int `json:"endLine"`
EndColumn *int `json:"endColumn"`
}
func (*SarifRegion) GetRdfRange ¶
func (r *SarifRegion) GetRdfRange() *rdf.Range
convert SARIF Region to RDF Range
* Supported SARIF: Line + Column Text region * Not supported SARIF: Offset + Length Text region ("charOffset", "charLength"), Binary region
example text:
abc\n def\n
region: "abc" SARIF: { "startLine": 1 }
= { "startLine": 1, "startColumn": 1, "endLine": 1, "endColumn": null }
-> RDF: { "start": { "line": 1 } }
region: "bc" SARIF: { "startLine": 1, "startColumn": 2 }
= { "startLine": 1, "startColumn": 2, "endLine": 1, "endColumn": null }
-> RDF: { "start": { "line": 1, "column": 2 }, "end": { "line": 1 } }
region: "a" SARIF: { "startLine": 1, "endColumn": 2 }
= { "startLine": 1, "startColumn": 1, "endLine": 1, "endColumn": 2 }
-> RDF: { "start": { "line": 1 }, "end": { "column": 2 } }
= { "start": { "line": 1 }, "end": { "line": 1, "column": 2 } }
region: "b" SARIF: { "startLine": 1, "startColumn": 2, "endColumn": 3 }
= { "startLine": 1, "startColumn": 2, "endLine": 1, "endColumn": 3 }
-> RDF: { "start": { "line": 1, "column": 2 }, "end": { "column": 3 } }
= { "start": { "line": 1, "column": 2 }, "end": { "line": 1, column": 3 } }
region: "abc\ndef" SARIF: { "startLine": 1, "endLine": 2 }
= { "startLine": 1, "startColumn": 1, "endLine": 2, "endColumn": null }
-> RDF: { "start": { "line": 1 }, "end": { "line": 2 } }
region: "abc\n" SARIF: { "startLine": 1, "endLine": 2, "endColumn": 1 }
= { "startLine": 1, "startColumn": 1, "endLine": 2, "endColumn": 1 }
-> RDF: { "start": { "line": 1 }, "end": { "line": 2, "column": 1 } }
zero width region: "{■}abc" SARIF: { "startLine": 1, "endColumn": 1 }
= { "startLine": 1, "startColumn": 1, "endLine": 1, "endColumn": 1 }
-> RDF: { "start": { "line": 1, "column": 1 } }
= { "start": { "line": 1, "column": 1 }, "end": { "line": 1, "column": 1 } }
type SarifRule ¶
type SarifRule struct {
ID string `json:"id"`
Name string `json:"name"`
ShortDescription SarifText `json:"shortDescription"`
FullDescription SarifText `json:"fullDescription"`
Help SarifText `json:"help"`
HelpURI string `json:"helpUri"`
DefaultConfiguration struct {
Level string `json:"level"`
Rank int `json:"rank"`
} `json:"defaultConfiguration"`
}