Skip to content
This repository was archived by the owner on Jul 16, 2023. It is now read-only.

feat: support type=lint suppression #1156

Merged
merged 2 commits into from
Jan 23, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* feat: add `allow-initialized` option to [`avoid-late-keyword`](https://dcm.dev/docs/individuals/rules/common/avoid-late-keyword).
* feat: add `ignored-types` option to [`avoid-late-keyword`](https://dcm.dev/docs/individuals/rules/common/avoid-late-keyword).
* fix: support tear-off methods for `check-unnecessary-nullable`.
* feat: support type=lint suppression.

## 5.4.0

Expand Down
18 changes: 12 additions & 6 deletions lib/src/analyzers/lint_analyzer/lint_analyzer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class LintAnalyzer {
);
}

// ignore: long-method
LintFileReport? _analyzeFile(
ResolvedUnitResult result,
LintAnalysisConfig config,
Expand All @@ -206,7 +207,11 @@ class LintAnalyzer {
return null;
}

final ignores = Suppression(result.content, result.lineInfo);
final ignores = Suppression(
result.content,
result.lineInfo,
supportsTypeLintIgnore: true,
);
final internalResult = InternalResolvedUnitResult(
filePath,
result.content,
Expand Down Expand Up @@ -240,11 +245,12 @@ class LintAnalyzer {
path: filePath,
relativePath: relativePath,
file: fileMetrics,
classes: Map.unmodifiable(classMetrics
.map<String, Report>((key, value) => MapEntry(key.name, value))),
functions: Map.unmodifiable(functionMetrics.map<String, Report>(
(key, value) => MapEntry(key.fullName, value),
)),
classes: Map.unmodifiable(
classMetrics.map((key, value) => MapEntry(key.name, value)),
),
functions: Map.unmodifiable(
functionMetrics.map((key, value) => MapEntry(key.fullName, value)),
),
issues: issues,
antiPatternCases: antiPatterns,
);
Expand Down
21 changes: 18 additions & 3 deletions lib/src/utils/suppression.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,30 @@ class Suppression {
static final _ignoreForFileMatcher =
RegExp('//[ ]*ignore_for_file:(.*)', multiLine: true);

static const _typeLint = 'type=lint';

final _ignoreMap = <int, List<String>>{};
final _ignoreForFileSet = <String>{};

bool _hasAllLintsSuppressed = false;

final LineInfo lineInfo;

/// Checks that the [id] is globally suppressed.
bool isSuppressed(String id) => _ignoreForFileSet.contains(_canonicalize(id));
bool isSuppressed(String id) =>
_hasAllLintsSuppressed || _ignoreForFileSet.contains(_canonicalize(id));

/// Checks that the [id] is suppressed for the [lineIndex].
bool isSuppressedAt(String id, int lineIndex) =>
isSuppressed(id) ||
(_ignoreMap[lineIndex]?.contains(_canonicalize(id)) ?? false);

/// Initialize a newly created [Suppression] with the given [content] and [lineInfo].
Suppression(String content, this.lineInfo) {
Suppression(
String content,
this.lineInfo, {
bool supportsTypeLintIgnore = false,
}) {
for (final match in _ignoreMatchers.allMatches(content)) {
final ids = match.group(1)!.split(',').map(_canonicalize);
final location = lineInfo.getLocation(match.start);
Expand All @@ -40,7 +50,12 @@ class Suppression {
}

for (final match in _ignoreForFileMatcher.allMatches(content)) {
_ignoreForFileSet.addAll(match.group(1)!.split(',').map(_canonicalize));
final suppressed = match.group(1)!.split(',').map(_canonicalize);
if (supportsTypeLintIgnore && suppressed.contains(_typeLint)) {
_hasAllLintsSuppressed = true;
} else {
_ignoreForFileSet.addAll(suppressed);
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions test/resources/suppression_all_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// ignore_for_file: type=lint

void main() {
const a = 5;
const b = a + 5;
}
24 changes: 24 additions & 0 deletions test/src/analyzers/lint_analyzer/models/suppression_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:test/test.dart';
import '../../../helpers/file_resolver.dart';

const _examplePath = 'test/resources/suppression_example.dart';
const _exampleAllPath = 'test/resources/suppression_all_example.dart';

void main() {
test('suppression in content', () async {
Expand All @@ -12,6 +13,7 @@ void main() {
final suppression = Suppression(
parseResult.content,
parseResult.lineInfo,
supportsTypeLintIgnore: true,
);

expect(suppression.isSuppressed('rule_id1'), isTrue);
Expand All @@ -26,4 +28,26 @@ void main() {
expect(suppression.isSuppressedAt('rule_id8', 9), isTrue);
expect(suppression.isSuppressedAt('rule_id9', 9), isTrue);
});

test('suppression with type=lint', () async {
final parseResult = await FileResolver.resolve(_exampleAllPath);

final suppression = Suppression(
parseResult.content,
parseResult.lineInfo,
supportsTypeLintIgnore: true,
);

expect(suppression.isSuppressed('rule_id1'), isTrue);
expect(suppression.isSuppressed('rule_id2'), isTrue);
expect(suppression.isSuppressed('rule_id3'), isTrue);
expect(suppression.isSuppressed('rule_id4'), isTrue);

expect(suppression.isSuppressedAt('rule_id4', 5), isTrue);
expect(suppression.isSuppressedAt('rule_id5', 5), isTrue);
expect(suppression.isSuppressedAt('rule_id6', 9), isTrue);
expect(suppression.isSuppressedAt('rule_id7', 9), isTrue);
expect(suppression.isSuppressedAt('rule_id8', 9), isTrue);
expect(suppression.isSuppressedAt('rule_id9', 9), isTrue);
});
}