Skip to content
Open
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
12 changes: 12 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import 'package:solid_lints/src/lints/avoid_final_with_getter/fixes/avoid_final_
import 'package:solid_lints/src/lints/avoid_global_state/avoid_global_state_rule.dart';
import 'package:solid_lints/src/lints/avoid_non_null_assertion/avoid_non_null_assertion_rule.dart';
import 'package:solid_lints/src/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart';
import 'package:solid_lints/src/lints/avoid_unnecessary_return_variable/avoid_unnecessary_return_variable_rule.dart';
import 'package:solid_lints/src/lints/avoid_unnecessary_setstate/avoid_unnecessary_set_state_rule.dart';
import 'package:solid_lints/src/lints/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_rule.dart';
import 'package:solid_lints/src/lints/avoid_unnecessary_type_assertions/fixes/avoid_unnecessary_type_assertions_fix.dart';
import 'package:solid_lints/src/lints/avoid_unrelated_type_assertions/avoid_unrelated_type_assertions_rule.dart';
import 'package:solid_lints/src/lints/avoid_unused_parameters/avoid_unused_parameters_rule.dart';
import 'package:solid_lints/src/lints/cyclomatic_complexity/cyclomatic_complexity_rule.dart';
import 'package:solid_lints/src/lints/double_literal_format/double_literal_format_rule.dart';
Expand All @@ -17,11 +20,14 @@ import 'package:solid_lints/src/lints/function_lines_of_code/function_lines_of_c
import 'package:solid_lints/src/lints/member_ordering/member_ordering_rule.dart';
import 'package:solid_lints/src/lints/named_parameters_ordering/fixes/named_parameters_ordering_fix.dart';
import 'package:solid_lints/src/lints/named_parameters_ordering/named_parameters_ordering_rule.dart';
import 'package:solid_lints/src/lints/newline_before_return/newline_before_return_rule.dart';
import 'package:solid_lints/src/lints/no_empty_block/no_empty_block_rule.dart';
import 'package:solid_lints/src/lints/no_equal_then_else/no_equal_then_else_rule.dart';
import 'package:solid_lints/src/lints/no_magic_number/no_magic_number_rule.dart';
import 'package:solid_lints/src/lints/number_of_parameters/number_of_parameters_rule.dart';
import 'package:solid_lints/src/lints/prefer_conditional_expressions/fixes/prefer_conditional_expressions_fix.dart';
import 'package:solid_lints/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart';
import 'package:solid_lints/src/lints/prefer_early_return/prefer_early_return_rule.dart';
import 'package:solid_lints/src/lints/prefer_first/fixes/prefer_first_fix.dart';
import 'package:solid_lints/src/lints/prefer_first/prefer_first_rule.dart';
import 'package:solid_lints/src/lints/prefer_last/fixes/prefer_last_fix.dart';
Expand Down Expand Up @@ -81,6 +87,12 @@ class SolidLintsPlugin extends Plugin {
// TODO: Add more lint rules and use analysisLoader
// for rules that need parameters
// For example: `CyclomaticComplexityRule(analysisLoader)`
AvoidUnnecessaryReturnVariableRule(),
AvoidUnnecessarySetStateRule(),
AvoidUnrelatedTypeAssertionsRule(),
NewlineBeforeReturnRule(),
NoEqualThenElseRule(),
PreferEarlyReturnRule(),
];

for (final lintRule in lintRules) {
Expand Down
41 changes: 31 additions & 10 deletions test/lints/auto_test_lint_offsets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ import 'package:analyzer_testing/analysis_rule/analysis_rule.dart';
import 'package:analyzer_testing/src/analysis_rule/pub_package_resolution.dart';
import 'package:collection/collection.dart';

import '../src/utils/auto_lint_data.dart';

mixin AutoTestLintOffsets on AnalysisRuleTest {
int _nextPlaceholderId = 0;
final Map<String, String> _placeholderToCode = {};
final Map<String, AutoLintData> _placeholderToData = {};

Future<void> assertAutoDiagnostics(String source) async {
try {
final placeholders = _placeholderToCode.entries
final placeholders = _placeholderToData.entries
.map(
(entry) => (
placeholder: entry.key,
code: entry.value,
data: entry.value,
index: source.indexOf(entry.key),
),
)
Expand All @@ -29,27 +31,46 @@ mixin AutoTestLintOffsets on AnalysisRuleTest {
}

expectedDiagnostics.add(
lint(match.index + replacedPlaceholdersDelta, match.code.length),
lint(
match.index + replacedPlaceholdersDelta,
match.data.code.length,
correctionContains: match.data.correctionContains,
messageContainsAll: match.data.messageContainsAll,
name: match.data.name,
contextMessages: match.data.contextMessages,
),
);
replacedPlaceholdersDelta +=
match.code.length - match.placeholder.length;
match.data.code.length - match.placeholder.length;
}

final resolvedSource = _placeholderToCode.entries.fold(
final resolvedSource = _placeholderToData.entries.fold(
source,
(resolved, entry) => resolved.replaceFirst(entry.key, entry.value),
(resolved, entry) => resolved.replaceFirst(entry.key, entry.value.code),
);

await assertDiagnostics(resolvedSource, expectedDiagnostics);
} finally {
_nextPlaceholderId = 0;
_placeholderToCode.clear();
_placeholderToData.clear();
}
}

String expectLint(String code) {
String expectLint(
String code, {
Pattern? correctionContains,
List<Pattern> messageContainsAll = const [],
String? name,
List<ExpectedContextMessage>? contextMessages,
}) {
final placeholder = '__AUTO_TEST_LINT_${_nextPlaceholderId++}__';
_placeholderToCode[placeholder] = code;
_placeholderToData[placeholder] = AutoLintData(
code: code,
correctionContains: correctionContains,
messageContainsAll: messageContainsAll,
name: name,
contextMessages: contextMessages,
);
return placeholder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import 'package:analyzer_testing/analysis_rule/analysis_rule.dart';
import 'package:solid_lints/src/lints/avoid_debug_print_in_release/avoid_debug_print_in_release_rule.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../auto_test_lint_offsets.dart';

void main() {
defineReflectiveSuite(() {
defineReflectiveTests(AvoidDebugPrintInReleaseRuleTest);
});
}

@reflectiveTest
class AvoidDebugPrintInReleaseRuleTest extends AnalysisRuleTest {
class AvoidDebugPrintInReleaseRuleTest extends AnalysisRuleTest
with AutoTestLintOffsets {
@override
void setUp() {
final flutter = newPackage('flutter');
Expand All @@ -33,154 +36,121 @@ export 'package:flutter/foundation.dart';
super.setUp();
}

@override
String get analysisRule => AvoidDebugPrintInReleaseRule.lintName;

void test_reports_debug_print_with_package_import() async {
await assertDiagnostics(
r'''
Future<void> test_reports_debug_print_with_package_import() async {
await assertAutoDiagnostics('''
import 'package:flutter/foundation.dart';

void test() {
debugPrint('This should be flagged');
${expectLint('debugPrint')}('This should be flagged');
}
''',
[lint(59, 10)],
);
''');
}

void test_reports_aliased_debug_print_from_package() async {
await assertDiagnostics(
r'''
Future<void> test_reports_aliased_debug_print_from_package() async {
await assertAutoDiagnostics('''
import 'package:flutter/foundation.dart' as f;

void test() {
f.debugPrint('This should be flagged');
f.${expectLint('debugPrint')}('This should be flagged');
}
''',
[lint(66, 10)],
);
''');
}

void test_reports_debug_print_as_callback() async {
await assertDiagnostics(
r'''
Future<void> test_reports_debug_print_as_callback() async {
await assertAutoDiagnostics('''
import 'package:flutter/foundation.dart';

void test() {
['a'].forEach(debugPrint);
['a'].forEach(${expectLint('debugPrint')});
}
''',
[lint(73, 10)],
);
''');
}

void test_reports_inside_kReleaseMode_guard() async {
await assertDiagnostics(
r'''
Future<void> test_reports_inside_kReleaseMode_guard() async {
await assertAutoDiagnostics('''
import 'package:flutter/foundation.dart';

void test() {
if (kReleaseMode) {
debugPrint('This should be flagged');
${expectLint('debugPrint')}('This should be flagged');
}
}
''',
[lint(83, 10)],
);
''');
}

void test_reports_inside_not_kDebugMode_guard() async {
await assertDiagnostics(
r'''
Future<void> test_reports_inside_not_kDebugMode_guard() async {
await assertAutoDiagnostics('''
import 'package:flutter/foundation.dart';

void test() {
if (!kDebugMode) {
debugPrint('Should still be flagged');
${expectLint('debugPrint')}('Should still be flagged');
}
}
''',
[lint(82, 10)],
);
''');
}

void test_does_not_report_inside_not_kReleaseMode() async {
await assertNoDiagnostics(
r'''
Future<void> test_does_not_report_inside_not_kReleaseMode() async {
await assertNoDiagnostics(r'''
import 'package:flutter/foundation.dart';

void test() {
if (!kReleaseMode) {
debugPrint('Safe');
}
}
''',
);
''');
}

void test_does_not_report_inside_kDebugMode() async {
await assertNoDiagnostics(
r'''
Future<void> test_does_not_report_inside_kDebugMode() async {
await assertNoDiagnostics(r'''
import 'package:flutter/foundation.dart';

void test() {
if (kDebugMode) {
debugPrint('Safe');
}
}
''',
);
''');
}

void test_no_report_when_debugPrint_is_not_from_foundation() async {
await assertNoDiagnostics(
r'''
Future<void> test_no_report_when_debugPrint_is_not_from_foundation() async {
await assertNoDiagnostics(r'''
void debugPrint(String message) {}

void test() {
debugPrint('Not a flutter call');
}
''',
);
''');
}

void test_reports_when_imported_via_material() async {
await assertDiagnostics(
r'''
Future<void> test_reports_when_imported_via_material() async {
await assertAutoDiagnostics('''
import 'package:flutter/material.dart';

void test() {
debugPrint('Flagged via material');
${expectLint('debugPrint')}('Flagged via material');
}
''',
[lint(57, 10)],
);
''');
}

void test_reports_when_imported_via_cupertino() async {
await assertDiagnostics(
r'''
Future<void> test_reports_when_imported_via_cupertino() async {
await assertAutoDiagnostics('''
import 'package:flutter/cupertino.dart';

void test() {
debugPrint('Flagged via cupertino');
${expectLint('debugPrint')}('Flagged via cupertino');
}
''',
[lint(58, 10)],
);
''');
}

void test_reports_debug_print_call_method() async {
await assertDiagnostics(
r'''
Future<void> test_reports_debug_print_call_method() async {
await assertAutoDiagnostics('''
import 'package:flutter/foundation.dart';

void test() {
debugPrint.call('This should be flagged');
${expectLint('debugPrint')}.call('This should be flagged');
}
''',
[lint(59, 10)],
);
''');
}
}
Loading
Loading