Skip to content

Commit 52e50c9

Browse files
authored
Remove all dynamic calls and properly enforce lint rule (#2582)
1 parent cd4fa41 commit 52e50c9

10 files changed

+66
-58
lines changed

analysis_options.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ analyzer:
1818
linter:
1919
rules:
2020
- always_declare_return_types
21+
- avoid_dynamic_calls
2122
- avoid_single_cascade_in_expression_statements
2223
- avoid_unused_constructor_parameters
2324
- annotate_overrides

analysis_options_presubmit.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ analyzer:
2121
linter:
2222
rules:
2323
- always_declare_return_types
24+
- avoid_dynamic_calls
2425
- avoid_single_cascade_in_expression_statements
2526
- avoid_unused_constructor_parameters
2627
- annotate_overrides

lib/src/dartdoc_options.dart

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -360,32 +360,32 @@ class ToolConfiguration {
360360
List<String> findCommand([String prefix = '']) {
361361
List<String> command;
362362
// If the command key is given, then it applies to all platforms.
363-
var commandFrom = toolMap.containsKey('${prefix}command')
363+
var commandFromKey = toolMap.containsKey('${prefix}command')
364364
? '${prefix}command'
365365
: '$prefix${Platform.operatingSystem}';
366-
if (toolMap.containsKey(commandFrom)) {
367-
if (toolMap[commandFrom].value is String) {
368-
command = [toolMap[commandFrom].toString()];
366+
if (toolMap.containsKey(commandFromKey)) {
367+
var commandFrom = toolMap[commandFromKey] as YamlNode;
368+
if (commandFrom.value is String) {
369+
command = [commandFrom.toString()];
369370
if (command[0].isEmpty) {
370371
throw DartdocOptionError(
371372
'Tool commands must not be empty. Tool $name command entry '
372-
'"$commandFrom" must contain at least one path.');
373+
'"$commandFromKey" must contain at least one path.');
373374
}
374-
} else if (toolMap[commandFrom] is YamlList) {
375-
command = (toolMap[commandFrom] as YamlList)
376-
.map<String>((node) => node.toString())
377-
.toList();
375+
} else if (commandFrom is YamlList) {
376+
command =
377+
commandFrom.map<String>((node) => node.toString()).toList();
378378
if (command.isEmpty) {
379379
throw DartdocOptionError(
380380
'Tool commands must not be empty. Tool $name command entry '
381-
'"$commandFrom" must contain at least one path.');
381+
'"$commandFromKey" must contain at least one path.');
382382
}
383383
} else {
384384
throw DartdocOptionError(
385385
'Tool commands must be a path to an executable, or a list of '
386386
'strings that starts with a path to an executable. '
387-
'The tool $name has a $commandFrom entry that is a '
388-
'${toolMap[commandFrom].runtimeType}');
387+
'The tool $name has a $commandFromKey entry that is a '
388+
'${commandFrom.runtimeType}');
389389
}
390390
}
391391
return command;
@@ -637,16 +637,17 @@ abstract class DartdocOption<T> {
637637
_OptionValueWithContext<Object> valueWithContext, String missingFilename);
638638

639639
/// Call [_onMissing] for every path that does not exist.
640-
void _validatePaths(_OptionValueWithContext<dynamic> valueWithContext) {
640+
void _validatePaths(_OptionValueWithContext<Object> valueWithContext) {
641641
if (!mustExist) return;
642642
assert(isDir || isFile);
643643
List<String> resolvedPaths;
644-
if (valueWithContext.value is String) {
644+
var value = valueWithContext.value;
645+
if (value is String) {
645646
resolvedPaths = [valueWithContext.resolvedValue];
646-
} else if (valueWithContext.value is List<String>) {
647-
resolvedPaths = valueWithContext.resolvedValue.toList();
648-
} else if (valueWithContext.value is Map<String, String>) {
649-
resolvedPaths = valueWithContext.resolvedValue.values.toList();
647+
} else if (value is List<String>) {
648+
resolvedPaths = valueWithContext.resolvedValue as List;
649+
} else if (value is Map<String, String>) {
650+
resolvedPaths = (valueWithContext.resolvedValue as Map).values.toList();
650651
} else {
651652
assert(
652653
false,
@@ -1159,19 +1160,18 @@ abstract class _DartdocFileOption<T> implements DartdocOption<T> {
11591160
_OptionValueWithContext<Object> _valueAtFromFile(Folder dir) {
11601161
var yamlFileData = _yamlAtDirectory(dir);
11611162
var contextPath = yamlFileData.canonicalDirectoryPath;
1162-
dynamic yamlData = yamlFileData.data ?? {};
1163+
Object yamlData = yamlFileData.data ?? {};
11631164
for (var key in keys) {
1164-
if (!yamlData.containsKey(key)) return null;
1165-
yamlData = yamlData[key] ?? {};
1165+
if (yamlData is Map && !yamlData.containsKey(key)) return null;
1166+
yamlData = (yamlData as Map)[key] ?? {};
11661167
}
11671168

1168-
dynamic returnData;
1169+
Object returnData;
11691170
if (_isListString) {
11701171
if (yamlData is YamlList) {
1171-
returnData = <String>[];
1172-
for (var item in yamlData) {
1173-
returnData.add(item.toString());
1174-
}
1172+
returnData = [
1173+
for (var item in yamlData) item.toString(),
1174+
];
11751175
}
11761176
} else if (yamlData is YamlMap) {
11771177
// TODO(jcollins-g): This special casing is unfortunate. Consider
@@ -1739,7 +1739,7 @@ Future<List<DartdocOption<Object>>> createDartdocOptions(
17391739
help: 'Generate ONLY the docs for the Dart SDK.'),
17401740
DartdocOptionArgSynth<String>('sdkDir',
17411741
(DartdocSyntheticOption<String> option, Folder dir) {
1742-
if (!option.parent['sdkDocs'].valueAt(dir) &&
1742+
if (!(option.parent['sdkDocs'].valueAt(dir) as bool) &&
17431743
(option.root['topLevelPackageMeta'].valueAt(dir) as PackageMeta)
17441744
.requiresFlutter) {
17451745
String flutterRoot = option.root['flutterRoot'].valueAt(dir);

lib/src/model/model_element.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ abstract class ModelElement extends Canonicalization
10971097
}
10981098
if (params == null && element is FunctionTypedElement) {
10991099
if (_originalMember != null) {
1100-
params = (_originalMember as dynamic).parameters;
1100+
params = (_originalMember as FunctionTypedElement).parameters;
11011101
} else {
11021102
params = (element as FunctionTypedElement).parameters;
11031103
}

lib/src/package_meta.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,12 @@ class _FilePackageMeta extends PubPackageMeta {
379379

380380
@override
381381
bool get requiresFlutter =>
382-
_pubspec['environment']?.containsKey('flutter') == true ||
383-
_pubspec['dependencies']?.containsKey('flutter') == true;
382+
_environment?.containsKey('flutter') == true ||
383+
_dependencies?.containsKey('flutter') == true;
384+
385+
YamlMap /*?*/ get _environment => _pubspec['environment'];
386+
387+
YamlMap /*?*/ get _dependencies => _pubspec['environment'];
384388

385389
@override
386390
File getReadmeContents() =>

test/dartdoc_options_test.dart

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void main() {
6363
dartdocOptionSetSynthetic.add(
6464
DartdocOptionSyntheticOnly<List<String>>('vegetableLoader',
6565
(DartdocSyntheticOption<List<String>> option, Folder dir) {
66-
if (option.root['mySpecialInteger'].valueAt(dir) > 20) {
66+
if ((option.root['mySpecialInteger'].valueAt(dir) as num) > 20) {
6767
return <String>['existing.dart'];
6868
} else {
6969
return <String>['not_existing.dart'];
@@ -81,7 +81,7 @@ void main() {
8181
dartdocOptionSetSynthetic.add(
8282
DartdocOptionArgSynth<String>('nonCriticalFileOption',
8383
(DartdocSyntheticOption<String> option, Folder dir) {
84-
return option.root['vegetableLoader'].valueAt(dir).first;
84+
return (option.root['vegetableLoader'].valueAt(dir) as List).first;
8585
}, resourceProvider, optionIs: OptionKind.file));
8686

8787
dartdocOptionSetFiles = DartdocOptionSet('dartdoc', resourceProvider);
@@ -637,13 +637,13 @@ dartdoc:
637637
equals(
638638
'Field dartdoc.fileOptionList from ${path.canonicalize(dartdocOptionsTwo.path)}, set to [existing.dart, thing/that/does/not/exist], resolves to missing path: '
639639
'"${path.joinAll([
640-
path.canonicalize(secondDir.path),
641-
'thing',
642-
'that',
643-
'does',
644-
'not',
645-
'exist'
646-
])}"'));
640+
path.canonicalize(secondDir.path),
641+
'thing',
642+
'that',
643+
'does',
644+
'not',
645+
'exist'
646+
])}"'));
647647
// It doesn't matter that this fails.
648648
expect(dartdocOptionSetFiles['nonCriticalFileOption'].valueAt(firstDir),
649649
equals(path.joinAll([path.canonicalize(firstDir.path), 'whatever'])));
@@ -663,9 +663,9 @@ dartdoc:
663663
equals(
664664
'Field dartdoc.fileOption from ${path.canonicalize(dartdocOptionsTwo.path)}, set to not existing, resolves to missing path: '
665665
'"${path.joinAll([
666-
path.canonicalize(secondDir.path),
667-
"not existing"
668-
])}"'));
666+
path.canonicalize(secondDir.path),
667+
"not existing"
668+
])}"'));
669669
});
670670

671671
test('DartdocOptionSetFile works for directory options', () {

test/end2end/dartdoc_integration_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void main() {
107107
});
108108

109109
test('missing a required file path prints a fatal-error', () async {
110-
var outputLines = [];
110+
var outputLines = <String>[];
111111
var impossiblePath = path.join(dartdocPath, 'impossible');
112112
await expectLater(
113113
() => subprocessLauncher.runStreamed(

tool/doc_packages.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,20 @@ Future<List<String>> _packageUrls(int page) {
124124
return http
125125
.get(Uri.parse('https://pub.dartlang.org/packages.json?page=$page'))
126126
.then((response) {
127-
return List<String>.from(json.decode(response.body)['packages']);
127+
var decodedJson = json.decode(response.body) as Map;
128+
return (decodedJson['packages'] as List).cast<String>();
128129
});
129130
}
130131

131132
Future<List<PackageInfo>> _getPackageInfos(List<String> packageUrls) {
132133
var futures = packageUrls.map((String p) {
133134
return http.get(Uri.parse(p)).then((response) {
134-
var decodedJson = json.decode(response.body);
135+
var decodedJson = json.decode(response.body) as Map;
135136
String name = decodedJson['name'];
136-
var versions = List<Version>.from(
137-
decodedJson['versions'].map((v) => Version.parse(v)));
137+
var versions = [
138+
for (var version in decodedJson['versions'] as List)
139+
Version.parse(version as String),
140+
];
138141
return PackageInfo(name, Version.primary(versions));
139142
});
140143
}).toList();
@@ -216,8 +219,8 @@ Future<void> _exec(String command, List<String> args,
216219
});
217220
}
218221

219-
bool _isOldSdkConstraint(var pubspecInfo) {
220-
var environment = pubspecInfo['environment'];
222+
bool _isOldSdkConstraint(Map<String, dynamic> pubspecInfo) {
223+
var environment = pubspecInfo['environment'] as Map;
221224
if (environment != null) {
222225
var sdk = environment['sdk'];
223226
if (sdk != null) {

tool/grind.dart

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:dartdoc/src/package_meta.dart';
1111
import 'package:grinder/grinder.dart';
1212
import 'package:path/path.dart' as path;
1313
import 'package:yaml/yaml.dart' as yaml;
14+
import 'package:yaml/yaml.dart';
1415

1516
import 'subprocess_launcher.dart';
1617

@@ -402,7 +403,8 @@ WarningsCollection jsonMessageIterableToWarnings(Iterable<Map> messageIterable,
402403
if (message.containsKey('level') &&
403404
message['level'] == 'WARNING' &&
404405
message.containsKey('data')) {
405-
warningTexts.add(message['data']['text']);
406+
var data = message['data'] as Map;
407+
warningTexts.add(data['text']);
406408
}
407409
}
408410
return warningTexts;
@@ -1001,15 +1003,11 @@ Future<void> checkChangelogHasVersion() async {
10011003

10021004
String _getPackageVersion() {
10031005
var pubspec = File('pubspec.yaml');
1004-
dynamic yamlDoc;
1005-
if (pubspec.existsSync()) {
1006-
yamlDoc = yaml.loadYaml(pubspec.readAsStringSync());
1007-
}
1008-
if (yamlDoc == null) {
1006+
if (!pubspec.existsSync()) {
10091007
fail('Cannot find pubspec.yaml in ${Directory.current}');
10101008
}
1011-
var version = yamlDoc['version'];
1012-
return version;
1009+
var yamlDoc = yaml.loadYaml(pubspec.readAsStringSync()) as YamlMap;
1010+
return yamlDoc['version'];
10131011
}
10141012

10151013
@Task('Rebuild generated files')

tool/subprocess_launcher.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ class SubprocessLauncher {
198198
if (result.containsKey('message')) {
199199
line = result['message'];
200200
} else if (result.containsKey('data')) {
201-
line = result['data']['text'];
201+
var data = result['data'] as Map;
202+
line = data['text'];
202203
}
203204
}
204205
return line.split('\n');

0 commit comments

Comments
 (0)