Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support error severity screening option #129

Merged
Merged
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
19 changes: 18 additions & 1 deletion packages/custom_lint/bin/custom_lint.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ import 'package:custom_lint/custom_lint.dart';

Future<void> entrypoint([List<String> args = const []]) async {
final parser = ArgParser()
..addFlag(
'fatal-infos',
help: 'Treat info level issues as fatal',
defaultsTo: true,
)
..addFlag(
'fatal-warnings',
help: 'Treat warning level issues as fatal',
defaultsTo: true,
)
..addFlag(
'watch',
help: "Watches plugins' sources and perform a hot-reload on change",
Expand All @@ -27,8 +37,15 @@ Future<void> entrypoint([List<String> args = const []]) async {
}

final watchMode = result['watch'] as bool;
final fatalInfos = result['fatal-infos'] as bool;
final fatalWarnings = result['fatal-warnings'] as bool;

await customLint(workingDirectory: Directory.current, watchMode: watchMode);
await customLint(
workingDirectory: Directory.current,
watchMode: watchMode,
fatalInfos: fatalInfos,
fatalWarnings: fatalWarnings,
);
}

void main([List<String> args = const []]) async {
Expand Down
49 changes: 41 additions & 8 deletions packages/custom_lint/lib/custom_lint.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;
Expand Down Expand Up @@ -36,6 +37,8 @@ q: Quit
Future<void> customLint({
bool watchMode = true,
required Directory workingDirectory,
bool fatalInfos = true,
bool fatalWarnings = true,
}) async {
// Reset the code
exitCode = 0;
Expand All @@ -46,6 +49,8 @@ Future<void> customLint({
channel,
watchMode: watchMode,
workingDirectory: workingDirectory,
fatalInfos: fatalInfos,
fatalWarnings: fatalWarnings,
);
} catch (_) {
exitCode = 1;
Expand All @@ -58,6 +63,8 @@ Future<void> _runServer(
ServerIsolateChannel channel, {
required bool watchMode,
required Directory workingDirectory,
required bool fatalInfos,
required bool fatalWarnings,
}) async {
final customLintServer = await CustomLintServer.start(
sendPort: channel.receivePort.sendPort,
Expand All @@ -84,10 +91,17 @@ Future<void> _runServer(
runner,
reload: false,
workingDirectory: workingDirectory,
fatalInfos: fatalInfos,
fatalWarnings: fatalWarnings,
);

if (watchMode) {
await _startWatchMode(runner, workingDirectory: workingDirectory);
await _startWatchMode(
runner,
workingDirectory: workingDirectory,
fatalInfos: fatalInfos,
fatalWarnings: fatalWarnings,
);
}
} finally {
await runner?.close();
Expand All @@ -105,15 +119,17 @@ Future<void> _runPlugins(
CustomLintRunner runner, {
required bool reload,
required Directory workingDirectory,
required bool fatalInfos,
required bool fatalWarnings,
}) async {
try {
final lints = await runner.getLints(reload: reload);

if (lints.any((lintsForFile) => lintsForFile.errors.isNotEmpty)) {
exitCode = 1;
}

_renderLints(lints, workingDirectory: workingDirectory);
_renderLints(
lints,
workingDirectory: workingDirectory,
fatalInfos: fatalInfos,
fatalWarnings: fatalWarnings,
);
} catch (err, stack) {
exitCode = 1;
stderr.writeln('$err\n$stack');
Expand All @@ -123,6 +139,8 @@ Future<void> _runPlugins(
void _renderLints(
List<AnalysisErrorsParams> lints, {
required Directory workingDirectory,
required bool fatalInfos,
required bool fatalWarnings,
}) {
var errors = lints.expand((lint) => lint.errors);

Expand Down Expand Up @@ -150,18 +168,31 @@ void _renderLints(
return;
}

exitCode = 1;
var hasErrors = false;
var hasWarnings = false;
var hasInfos = false;
for (final error in errors) {
stdout.writeln(
' ${_relativeFilePath(error.location.file, workingDirectory)}:${error.location.startLine}:${error.location.startColumn}'
' • ${error.message} • ${error.code} • ${error.severity.name}',
);
hasErrors = hasErrors || error.severity == AnalysisErrorSeverity.ERROR;
hasWarnings =
hasWarnings || error.severity == AnalysisErrorSeverity.WARNING;
hasInfos = hasInfos || error.severity == AnalysisErrorSeverity.INFO;
}

if (hasErrors || (fatalWarnings && hasWarnings) || (fatalInfos && hasInfos)) {
exitCode = 1;
return;
}
}

Future<void> _startWatchMode(
CustomLintRunner runner, {
required Directory workingDirectory,
required bool fatalInfos,
required bool fatalWarnings,
}) async {
if (stdin.hasTerminal) {
stdin
Expand All @@ -183,6 +214,8 @@ Future<void> _startWatchMode(
runner,
reload: true,
workingDirectory: workingDirectory,
fatalInfos: fatalInfos,
fatalWarnings: fatalWarnings,
);
break;
case 'q':
Expand Down
68 changes: 68 additions & 0 deletions packages/custom_lint/test/cli_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:io';

import 'package:analyzer/error/error.dart';
import 'package:test/test.dart';

import '../bin/custom_lint.dart' as cli;
Expand Down Expand Up @@ -86,6 +87,73 @@ lib/custom_lint_client.dart:13:29: Error: Undefined name 'createPlugin'.
);
});

test('exits with 0 when pass argument `--no-fatal-infos`', () async {
final plugin = createPlugin(name: 'test_lint', main: helloWordPluginSource);

final app = createLintUsage(
source: {'lib/main.dart': 'void fn() {}'},
plugins: {'test_lint': plugin.uri},
name: 'test_app',
);

await runWithIOOverride(
(out, err) async {
await cli.entrypoint(['--no-fatal-infos']);

expect(exitCode, 0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you test that out still logs the infos/warnings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed commit 882b9bb

expect(
out.join(),
completion(
matchIgnoringAnsi(contains, '''
lib/main.dart:1:6 • Hello world • hello_world • INFO
'''),
),
);
expect(err, emitsDone);
},
currentDirectory: app,
);
});

test(
'exits with 0 when found warning and pass argument `--no-fatal-warnings`',
() async {
final plugin = createPlugin(
name: 'test_lint',
main: createPluginSource([
TestLintRule(
code: 'hello_world',
message: 'Hello world',
errorSeverity: ErrorSeverity.WARNING,
),
]),
);

final app = createLintUsage(
source: {'lib/main.dart': 'void fn() {}'},
plugins: {'test_lint': plugin.uri},
name: 'test_app',
);

await runWithIOOverride(
(out, err) async {
await cli.entrypoint(['--no-fatal-warnings']);

expect(exitCode, 0);
expect(
out.join(),
completion(
matchIgnoringAnsi(contains, '''
lib/main.dart:1:6 • Hello world • hello_world • WARNING
'''),
),
);
expect(err, emitsDone);
},
currentDirectory: app,
);
});

test('CLI lists warnings from all plugins and set exit code', () async {
final plugin = createPlugin(name: 'test_lint', main: helloWordPluginSource);
final plugin2 = createPlugin(name: 'test_lint2', main: oyPluginSource);
Expand Down
7 changes: 6 additions & 1 deletion packages/custom_lint/test/create_project.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:io';

import 'package:analyzer/error/error.dart';
import 'package:path/path.dart';
import 'package:test/scaffolding.dart';

Expand Down Expand Up @@ -30,6 +31,7 @@ class TestLintRule {
this.onVariable = '',
this.ruleMembers = '',
this.fixes = const [],
this.errorSeverity = ErrorSeverity.INFO,
});

final String code;
Expand All @@ -39,6 +41,7 @@ class TestLintRule {
final String onVariable;
final String ruleMembers;
final List<TestLintFix> fixes;
final ErrorSeverity errorSeverity;
}

class TestLintFix {
Expand Down Expand Up @@ -103,7 +106,9 @@ class ${fix.name} extends DartFix {
class ${rule.code} extends DartLintRule {
${rule.code}()
: super(
code: LintCode(name: '${rule.code}', problemMessage: '${rule.message}'),
code: LintCode(name: '${rule.code}',
problemMessage: '${rule.message}',
errorSeverity: ErrorSeverity.${rule.errorSeverity.displayName.toUpperCase()}),
);

$fixes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[hello_world] 1990-01-01T00:00:00.000 Hello world
[hello_world] 1990-01-01T00:00:00.000 Plugin hello_world threw while analyzing app/lib/another.dart:
[hello_world] 1990-01-01T00:00:00.000 Bad state: fail
[hello_world] 1990-01-01T00:00:00.000 #0 hello_world.run.<anonymous closure> (package:test_lint/test_lint.dart:26:3)
[hello_world] 1990-01-01T00:00:00.000 #0 hello_world.run.<anonymous closure> (package:test_lint/test_lint.dart:28:3)
4 changes: 3 additions & 1 deletion packages/custom_lint/test/server_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,9 @@ if (node.name.lexeme == "fail") {
});

group('hot-reload', () {
test('Supports starting custom_lint twice in watch mode at once', () async {
test(
timeout: const Timeout.factor(2),
'Supports starting custom_lint twice in watch mode at once', () async {
final plugin = createPlugin(
name: 'test_lint',
main: helloWordPluginSource,
Expand Down