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

fix: remove duplicated highlights and ignore void function calls #829

Merged
merged 4 commits into from May 16, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
## Unreleased

* fix: [`avoid-border-all`](https://dartcodemetrics.dev/docs/rules/flutter/avoid-border-all) is triggered even when it is not a const.
* fix: remove duplicated and ignore void function calls for [`prefer-moving-to-variable`](https://dartcodemetrics.dev/docs/rules/common/prefer-moving-to-variable).

## 4.15.1

Expand Down
Expand Up @@ -7,8 +7,6 @@ class _Visitor extends RecursiveAstVisitor<void> {

@override
void visitBlockFunctionBody(BlockFunctionBody node) {
super.visitBlockFunctionBody(node);

final visitor = _BlockVisitor();
node.visitChildren(visitor);

Expand Down Expand Up @@ -39,7 +37,8 @@ class _BlockVisitor extends RecursiveAstVisitor<void> {

@override
void visitMethodInvocation(MethodInvocation node) {
if (node.parent is CascadeExpression) {
if (node.parent is CascadeExpression ||
(node.staticType?.isVoid ?? false)) {
return;
}

Expand Down Expand Up @@ -75,8 +74,7 @@ class _BlockVisitor extends RecursiveAstVisitor<void> {
final visitedBlock = visitedInvocation.thisOrAncestorOfType<Block>();
final parentBlock = node.thisOrAncestorOfType<Block>();

// ignore: avoid-late-keyword
late final grandParentBlock = parentBlock?.thisOrAncestorMatching(
final grandParentBlock = parentBlock?.thisOrAncestorMatching(
(block) => block is Block && block != parentBlock,
);

Expand Down
@@ -0,0 +1,50 @@
void main() {
final someValue = 'value';

methodWithArguments('hello');
methodWithArguments('hello', 'world');

methodWithArguments('world'); // LINT
methodWithArguments('world'); // LINT

methodWithArguments(someValue); // LINT
methodWithArguments(someValue); // LINT

final someOtherValue = 'otherValue';
methodWithArguments(someOtherValue);
methodWithArguments(someValue); // LINT

methodWithNamedArguments(age: 1);
methodWithNamedArguments(age: 1, firstName: '');

methodWithNamedArguments(firstName: 'hello'); // LINT
methodWithNamedArguments(firstName: 'hello'); // LINT

methodWithNamedArguments(lastName: 'last'); // LINT

if (true) {
methodWithNamedArguments(lastName: 'last'); // LINT
}

methodWithMixedArguments(someValue);
methodWithMixedArguments(someOtherValue);

methodWithMixedArguments(someValue, named: 'name'); // LINT
methodWithMixedArguments(someValue, named: 'name'); // LINT
}

String methodWithArguments(String firstRegular, String secondRegular) {
return '';
}

String methodWithNamedArguments({
String firstName,
String lastName,
int age,
}) {
return '';
}

String methodWithMixedArguments(String regular, {int? named}) {
return '';
}
@@ -0,0 +1,54 @@
void main() {
final state = State();

final someValue = 'value';

state.methodWithArguments('hello');
state.methodWithArguments('hello', 'world');

state.methodWithArguments('world'); // LINT
state.methodWithArguments('world'); // LINT

state.methodWithArguments(someValue); // LINT
state.methodWithArguments(someValue); // LINT

final someOtherValue = 'otherValue';
state.methodWithArguments(someOtherValue);
state.methodWithArguments(someValue); // LINT

state.methodWithNamedArguments(age: 1);
state.methodWithNamedArguments(age: 1, firstName: '');

state.methodWithNamedArguments(firstName: 'hello'); // LINT
state.methodWithNamedArguments(firstName: 'hello'); // LINT

state.methodWithNamedArguments(lastName: 'last'); // LINT

if (true) {
state.methodWithNamedArguments(lastName: 'last'); // LINT
}

state.methodWithMixedArguments(someValue);
state.methodWithMixedArguments(someOtherValue);

state.methodWithMixedArguments(someValue, named: 'name'); // LINT
state.methodWithMixedArguments(someValue, named: 'name'); // LINT
}

class State {
String methodWithArguments(String firstRegular, String secondRegular) {
return '';
}

String methodWithNamedArguments({
String firstName,
String lastName,
int age,
}) {
return '';
}

String methodWithMixedArguments(String regular, {int? named}) {
return '';
}
}
Expand Up @@ -22,8 +22,11 @@ void main() {
Theme.from().value.runtimeType; // LINT
Theme.from().value.length; // LINT

Theme.from().someMethod(); // LINT
Theme.from().someMethod(); // LINT
Theme.from().someMethod();
Theme.from().someMethod();

Theme.from().notVoidMethod(); // LINT
Theme.from().notVoidMethod(); // LINT

getValue(); // LINT
getValue(); // LINT
Expand All @@ -44,6 +47,12 @@ class Theme {
string.indexOf('').sign.bitLength.isEven; // LINT
string.indexOf('').sign.isOdd; // LINT
}

String notVoidMethod() {
final string = 'str';

return string;
}
}

String getValue() => 'hello';
@@ -0,0 +1,49 @@
class BlocTest {
final state = State();

FutureOr<void> mapEvent(
TestEvent event,
Emitter<TestState> emit,
) {
return event.map<FutureOr<void>>(
init: (_) async {
emit(state.copyWith(isLoading: true)); // LINT

const result = [];

var newState = state.copyWith(dataList: result); // LINT

if (result.isEmpty) {
newState = newState.copyWith(dataList: [], isLoading: false);
} else {
newState = newState.copyWith(dataList: result, isLoading: false);
}

emit(state);
},
checkProviders: (_) async {
emit(state.copyWith(isLoading: true)); // LINT

const result = [];

if (result.isEmpty) {
emit(state.copyWith(dataList: [])); // LINT
} else {
emit(state.copyWith(dataList: result));
}
},
);
}

void emit(Object value) {}
}

class TestEvent {
FutureOr<void> map<T>({Function init, Function checkProviders}) {}
}

class State {
State copyWith({List<Object> dataList, bool isLoading}) {
return State();
}
}
Expand Up @@ -5,6 +5,12 @@ import 'package:test/test.dart';
import '../../../../../helpers/rule_test_helper.dart';

const _examplePath = 'prefer_moving_to_variable/examples/example.dart';
const _argumentsExamplePath =
'prefer_moving_to_variable/examples/arguments_example.dart';
const _argumentsWithObjectExamplePath =
'prefer_moving_to_variable/examples/arguments_with_object_example.dart';
const _scopeExamplePath =
'prefer_moving_to_variable/examples/scope_example.dart';
const _cascadeExamplePath =
'prefer_moving_to_variable/examples/cascade_example.dart';

Expand Down Expand Up @@ -40,12 +46,12 @@ void main() {
20,
22,
23,
25,
26,
28,
29,
44,
45,
31,
32,
47,
48,
],
startColumns: [
19,
Expand Down Expand Up @@ -80,8 +86,8 @@ void main() {
'Theme.after().value',
'Theme.from().value',
'Theme.from().value',
'Theme.from().someMethod()',
'Theme.from().someMethod()',
'Theme.from().notVoidMethod()',
'Theme.from().notVoidMethod()',
'getValue()',
'getValue()',
"string.indexOf('').sign",
Expand Down Expand Up @@ -110,6 +116,96 @@ void main() {
);
});

test(
'reports about found issues for invocations with arguments example',
() async {
final unit =
await RuleTestHelper.resolveFromFile(_argumentsExamplePath);
final issues = PreferMovingToVariableRule().check(unit);

RuleTestHelper.verifyIssues(
issues: issues,
startLines: [7, 8, 10, 11, 15, 20, 21, 23, 26, 32, 33],
startColumns: [3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3],
locationTexts: [
"methodWithArguments('world')",
"methodWithArguments('world')",
'methodWithArguments(someValue)',
'methodWithArguments(someValue)',
'methodWithArguments(someValue)',
"methodWithNamedArguments(firstName: 'hello')",
"methodWithNamedArguments(firstName: 'hello')",
"methodWithNamedArguments(lastName: 'last')",
"methodWithNamedArguments(lastName: 'last')",
"methodWithMixedArguments(someValue, named: 'name')",
"methodWithMixedArguments(someValue, named: 'name')",
],
messages: [
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
],
);
},
);

test(
'reports about found issues for invocations on object with arguments example',
() async {
final unit = await RuleTestHelper.resolveFromFile(
_argumentsWithObjectExamplePath,
);
final issues = PreferMovingToVariableRule().check(unit);

RuleTestHelper.verifyIssues(
issues: issues,
startLines: [9, 10, 12, 13, 17, 22, 23, 25, 28, 34, 35],
startColumns: [3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3],
locationTexts: [
"state.methodWithArguments('world')",
"state.methodWithArguments('world')",
'state.methodWithArguments(someValue)',
'state.methodWithArguments(someValue)',
'state.methodWithArguments(someValue)',
"state.methodWithNamedArguments(firstName: 'hello')",
"state.methodWithNamedArguments(firstName: 'hello')",
"state.methodWithNamedArguments(lastName: 'last')",
"state.methodWithNamedArguments(lastName: 'last')",
"state.methodWithMixedArguments(someValue, named: 'name')",
"state.methodWithMixedArguments(someValue, named: 'name')",
],
messages: [
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
'Prefer moving repeated invocations to variable and use it instead.',
],
);
},
);

test('reports no issues for scope', () async {
final unit = await RuleTestHelper.resolveFromFile(_scopeExamplePath);
final issues = PreferMovingToVariableRule().check(unit);

RuleTestHelper.verifyNoIssues(issues);
});

test('reports no issues for cascade', () async {
final unit = await RuleTestHelper.resolveFromFile(_cascadeExamplePath);
final issues = PreferMovingToVariableRule().check(unit);
Expand Down