diff --git a/README.md b/README.md index 624ed2a..c34311b 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,11 @@ dscanner -S source/ dscanner --report source/ ``` +The `--report` switch includes all information, plus cheap to compute autofixes +that are already resolved ahead of time, as well as the names for the autofixes +that need to be resolved using the `--resolveMessage` switch like described +below. + You can also specify custom formats using `-f` / `--errorFormat`, where there are also built-in formats for GitHub Actions: @@ -101,7 +106,7 @@ dscanner -S -f github source/ dscanner -S -f '{filepath}({line}:{column})[{type}]: {message}' source/ ``` -To collect automatic issue fixes for a given location use +To resolve automatic issue fixes for a given location use ```sh # collecting automatic issue fixes diff --git a/src/dscanner/reports.d b/src/dscanner/reports.d index a54bac3..c35d9b0 100644 --- a/src/dscanner/reports.d +++ b/src/dscanner/reports.d @@ -55,6 +55,9 @@ class DScannerJsonReporter private static JSONValue toJson(Issue issue) { + import std.sumtype : match; + import dscanner.analysis.base : AutoFix; + // dfmt off JSONValue js = JSONValue([ "key": JSONValue(issue.message.key), @@ -80,6 +83,27 @@ class DScannerJsonReporter "message": JSONValue(a.message), ]) ).array + ), + "autofixes": JSONValue( + issue.message.autofixes.map!(a => + JSONValue([ + "name": JSONValue(a.name), + "replacements": a.replacements.match!( + (const AutoFix.CodeReplacement[] replacements) => JSONValue( + replacements.map!(r => JSONValue([ + "range": JSONValue([ + JSONValue(r.range[0]), + JSONValue(r.range[1]) + ]), + "newText": JSONValue(r.newText) + ])).array + ), + (const AutoFix.ResolveContext _) => JSONValue( + "resolvable" + ) + ) + ]) + ).array ) ]); // dfmt on diff --git a/tests/it/source_autofix.d b/tests/it/source_autofix.d index 98b43a8..170244c 100644 --- a/tests/it/source_autofix.d +++ b/tests/it/source_autofix.d @@ -2,5 +2,11 @@ struct S { int myProp() @property { + static if (a) + { + } + else if (b) + { + } } } diff --git a/tests/it/source_autofix.report.json b/tests/it/source_autofix.report.json index 11d08f4..f1ff0b9 100644 --- a/tests/it/source_autofix.report.json +++ b/tests/it/source_autofix.report.json @@ -15,11 +15,81 @@ "message": "Zero-parameter '@property' function should be marked 'const', 'inout', or 'immutable'.", "name": "function_attribute_check", "supplemental": [], + "type": "warn", + "autofixes": [ + { + "name": "Mark function `const`", + "replacements": [ + { + "newText": " const", + "range": [ + 24, + 24 + ] + } + ] + }, + { + "name": "Mark function `inout`", + "replacements": [ + { + "newText": " inout", + "range": [ + 24, + 24 + ] + } + ] + }, + { + "name": "Mark function `immutable`", + "replacements": [ + { + "newText": " immutable", + "range": [ + 24, + 24 + ] + } + ] + } + ] + }, + { + "autofixes": [ + { + "name": "Insert `static`", + "replacements": [ + { + "newText": "static ", + "range": [ + 69, + 69 + ] + } + ] + }, + { + "name": "Wrap '{}' block around 'if'", + "replacements": "resolvable" + } + ], + "column": 3, + "endColumn": 10, + "endIndex": 71, + "endLine": 8, + "fileName": "it/source_autofix.d", + "index": 64, + "key": "dscanner.suspicious.static_if_else", + "line": 8, + "message": "Mismatched static if. Use 'else static if' here.", + "name": "static_if_else_check", + "supplemental": [], "type": "warn" } ], - "lineOfCodeCount": 0, - "statementCount": 0, + "lineOfCodeCount": 3, + "statementCount": 4, "structCount": 1, "templateCount": 0, "undocumentedPublicSymbols": 0