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

feat: ignore tear-off methods for avoid-unused-parameters #1126

Merged
merged 2 commits into from
Dec 28, 2022
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 @@ -2,6 +2,7 @@

## Unreleased

* feat: ignore tear-off methods for [`avoid-unused-parameters`](https://dartcodemetrics.dev/docs/rules/common/avoid-unused-parameters).
* feat: show warning for rules without config that require config to work.
* fix: correctly handle FunctionExpressions for [`avoid-redundant-async`](https://dartcodemetrics.dev/docs/rules/common/avoid-redundant-async).
* feat: support ignoring nesting for [`prefer-conditional-expressions`](https://dartcodemetrics.dev/docs/rules/common/prefer-conditional-expressions).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@ class _Visitor extends RecursiveAstVisitor<void> {
void visitMethodDeclaration(MethodDeclaration node) {
super.visitMethodDeclaration(node);

final isOverride = node.metadata.any(
(node) =>
node.name.name == 'override' && node.atSign.type == TokenType.AT,
);

if (!isOverride && _hasRedundantAsync(node.body)) {
if (!isOverride(node.metadata) && _hasRedundantAsync(node.body)) {
_nodes.add(node);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// ignore_for_file: public_member_api_docs

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ class _Visitor extends RecursiveAstVisitor<void> {
return;
}

final isOverride = node.metadata.any(
(node) =>
node.name.name == 'override' && node.atSign.type == TokenType.AT,
);
final isTearOff = _usedAsTearOff(node);

if (!isOverride) {
if (!isOverride(node.metadata) && !isTearOff) {
_unusedParameters.addAll(
_getUnusedParameters(
node.body,
Expand Down Expand Up @@ -77,6 +74,18 @@ class _Visitor extends RecursiveAstVisitor<void> {
bool _hasNoUnderscoresInName(FormalParameter parameter) =>
parameter.name != null &&
parameter.name!.lexeme.replaceAll('_', '').isNotEmpty;

bool _usedAsTearOff(MethodDeclaration node) {
final name = node.name.lexeme;
if (!Identifier.isPrivateName(name)) {
return false;
}

final visitor = _InvocationsVisitor(name);
node.root.visitChildren(visitor);

return visitor.hasTearOffInvocations;
}
}

class _IdentifiersVisitor extends RecursiveAstVisitor<void> {
Expand All @@ -92,3 +101,22 @@ class _IdentifiersVisitor extends RecursiveAstVisitor<void> {
}
}
}

class _InvocationsVisitor extends RecursiveAstVisitor<void> {
final String methodName;

bool hasTearOffInvocations = false;

_InvocationsVisitor(this.methodName);

@override
void visitSimpleIdentifier(SimpleIdentifier node) {
if (node.name == methodName &&
node.staticElement is MethodElement &&
node.parent! is MethodInvocation) {
hasTearOffInvocations = true;
}

super.visitSimpleIdentifier(node);
}
}
6 changes: 6 additions & 0 deletions lib/src/utils/node_utils.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:source_span/source_span.dart';

import '../analyzers/lint_analyzer/models/internal_resolved_unit_result.dart';
Expand Down Expand Up @@ -37,6 +38,11 @@ SourceSpan nodeLocation({
);
}

bool isOverride(List<Annotation> metadata) => metadata.any(
(node) =>
node.name.name == 'override' && node.atSign.type == TokenType.AT,
);

bool isEntrypoint(String name, NodeList<Annotation> metadata) =>
name == 'main' ||
_hasPragmaAnnotation(metadata) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const _correctExamplePath =
'avoid_unused_parameters/examples/correct_example.dart';
const _incorrectExamplePath =
'avoid_unused_parameters/examples/incorrect_example.dart';
const _tearOffExamplePath =
'avoid_unused_parameters/examples/tear_off_example.dart';

void main() {
group('AvoidUnusedParametersRule', () {
Expand Down Expand Up @@ -61,5 +63,26 @@ void main() {
],
);
});

test('should report about found issues for tear-offs', () async {
final unit = await RuleTestHelper.resolveFromFile(_tearOffExamplePath);
final issues = AvoidUnusedParametersRule().check(unit);

RuleTestHelper.verifyIssues(
issues: issues,
startLines: [8, 13, 13],
startColumns: [36, 23, 43],
locationTexts: [
'int value',
'String firstString',
'String secondString',
],
messages: [
'Parameter is unused.',
'Parameter is unused.',
'Parameter is unused.',
],
);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class TestClass {
String value;

void _someMethod(Function(String, int) callback) {
callback();
}

void _otherMethod(String string, int value) {
print(string);
}

// LINT
void _anotherMethod(String firstString, String secondString) {
someMethod(_otherMethod);
_someOtherMethod(value);
}

// LINT
_someOtherMethod(String value) {}
}