diff --git a/lib/src/rules/prefer_collection_literals.dart b/lib/src/rules/prefer_collection_literals.dart index b95868de6..a708611bb 100644 --- a/lib/src/rules/prefer_collection_literals.dart +++ b/lib/src/rules/prefer_collection_literals.dart @@ -66,10 +66,7 @@ class _Visitor extends SimpleAstVisitor { final constructorName = node.constructorName.name?.name; // Lists, Maps. - if (DartTypeUtilities.isClass(node.staticType, 'List', 'dart.core') || - DartTypeUtilities.isClass(node.staticType, 'Map', 'dart.core') || - DartTypeUtilities.isClass( - node.staticType, 'LinkedHashMap', 'dart.collection')) { + if (isList(node) || isMap(node) || isHashMap(node)) { if (constructorName == null && node.argumentList.arguments.isEmpty) { rule.reportLint(node); } @@ -77,14 +74,44 @@ class _Visitor extends SimpleAstVisitor { } // Sets. - if (DartTypeUtilities.isClass(node.staticType, 'Set', 'dart.core') || - DartTypeUtilities.isClass( - node.staticType, 'LinkedHashSet', 'dart.collection')) { - if (constructorName == null || - constructorName == 'from' || - constructorName == 'of') { + if (isSet(node) || isHashSet(node)) { + // Skip: LinkedHashSet s = ...; + var parent = node.parent; + if (parent is VariableDeclaration) { + var parent2 = parent.parent; + if (parent2 is VariableDeclarationList) { + var assignmentType = parent2.type?.type; + if (assignmentType != null && + !DartTypeUtilities.isClass(assignmentType, 'Set', 'dart.core')) { + return; + } + } + } + + if (constructorName == null) { rule.reportLint(node); + } else if (constructorName == 'from' || constructorName == 'of') { + var args = node.argumentList.arguments; + if (args.length != 1) { + return; + } + var arg = args.first; + if (arg is ListLiteral || arg is ListLiteral2) { + rule.reportLint(node); + } } } } + + // todo (pq): migrate to using typeProvider + bool isSet(Expression expression) => + DartTypeUtilities.isClass(expression.staticType, 'Set', 'dart.core'); + bool isHashSet(Expression expression) => DartTypeUtilities.isClass( + expression.staticType, 'LinkedHashSet', 'dart.collection'); + bool isList(Expression expression) => + DartTypeUtilities.isClass(expression.staticType, 'List', 'dart.core'); + bool isMap(Expression expression) => + DartTypeUtilities.isClass(expression.staticType, 'Map', 'dart.core'); + bool isHashMap(Expression expression) => DartTypeUtilities.isClass( + expression.staticType, 'LinkedHashMap', 'dart.collection'); } diff --git a/test/mock_sdk.dart b/test/mock_sdk.dart index 0e583fb31..bd251c4b8 100644 --- a/test/mock_sdk.dart +++ b/test/mock_sdk.dart @@ -113,6 +113,8 @@ class Iterator { } abstract class Iterable { + const Iterable(); + const factory Iterable.empty() = Iterable; Iterator get iterator; bool contains(Object element); E firstWhere(bool test(E element), { E orElse()}); @@ -135,13 +137,19 @@ abstract class List implements Iterable { int indexOf(Object element); bool get isEmpty; bool get isNotEmpty; + Set toSet() => new Set.from(this); } abstract class Map extends Object { /* external */ factory Map(); factory Map.from(Map other) = LinkedHashMap.from; + factory Map.fromIterable(Iterable iterable, + {K key(element), V value(element)}) = LinkedHashMap.fromIterable; + factory Map.fromIterables(Iterable keys, Iterable values) = + LinkedHashMap.fromIterables; factory Map.of(Map other) = LinkedHashMap.of; factory Map.identity() = LinkedHashMap.identity; + /* external */ factory Map.unmodifiable(Map other); Iterable get keys; bool get isEmpty; bool get isNotEmpty; @@ -207,6 +215,9 @@ abstract class LinkedHashMap implements Map { bool isValidKey(potentialKey)}); /* external */ factory LinkedHashMap.identity(); factory LinkedHashMap.from(Map other); + factory LinkedHashMap.fromIterable(Iterable iterable, + {K key(element), V value(element)}); + factory LinkedHashMap.fromIterables(Iterable keys, Iterable values); factory LinkedHashMap.of(Map other) => new LinkedHashMap()..addAll(other); } diff --git a/test/rules/prefer_collection_literals.dart b/test/rules/prefer_collection_literals.dart index d70919771..ac73234aa 100644 --- a/test/rules/prefer_collection_literals.dart +++ b/test/rules/prefer_collection_literals.dart @@ -47,4 +47,13 @@ void main() { var ss2 = new LinkedHashSet(); // LINT var ss3 = LinkedHashSet.from([]); // LINT var ss4 = LinkedHashSet.of([]); // LINT + + Set ss5 = LinkedHashSet(); // LINT + LinkedHashSet ss6 = LinkedHashSet(); // OK + + Set ss7 = LinkedHashSet.from([1, 2, 3]); // LINT + LinkedHashSet ss8 = LinkedHashSet.from([1, 2, 3]); // OK + + Iterable iter = Iterable.empty(); // OK + var sss = Set.from(iter); // OK }