analysis options and lint cleanup (#183)
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 572dd23..8f13782 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1 +1,30 @@
include: package:lints/recommended.yaml
+
+analyzer:
+ language:
+ strict-casts: true
+ strict-inference: true
+ strict-raw-types: true
+
+linter:
+ rules:
+ - always_declare_return_types
+ - avoid_unused_constructor_parameters
+ - cancel_subscriptions
+ - directives_ordering
+ - lines_longer_than_80_chars
+ - literal_only_boolean_expressions
+ - missing_whitespace_between_adjacent_strings
+ - no_adjacent_strings_in_list
+ - no_runtimeType_toString
+ - omit_local_variable_types
+ - package_api_docs
+ - prefer_relative_imports
+ - prefer_single_quotes
+ - test_types_in_equals
+ - throw_in_finally
+ - type_annotate_public_apis
+ - unawaited_futures
+ - unnecessary_await_in_return
+ - unnecessary_lambdas
+ - use_super_parameters
diff --git a/example/ga.dart b/example/ga.dart
index 7d4c645..1fc8491 100644
--- a/example/ga.dart
+++ b/example/ga.dart
@@ -7,7 +7,7 @@
import 'package:usage/usage_io.dart';
-void main(List args) async {
+void main(List<String> args) async {
final defaultUA = 'UA-188575324-1';
if (args.isEmpty) {
@@ -17,7 +17,7 @@
print('pinging ${args.first}');
}
- String ua = args.isEmpty ? defaultUA : args.first;
+ var ua = args.isEmpty ? defaultUA : args.first;
Analytics ga = AnalyticsIO(ua, 'ga_test', '3.0');
diff --git a/lib/src/usage_impl.dart b/lib/src/usage_impl.dart
index 40f2e13..51a2b9a 100644
--- a/lib/src/usage_impl.dart
+++ b/lib/src/usage_impl.dart
@@ -74,7 +74,7 @@
final ThrottlingBucket _bucket = ThrottlingBucket(20);
final Map<String, dynamic> _variableMap = {};
- final List<Future> _futures = [];
+ final List<Future<void>> _futures = [];
@override
AnalyticsOpt analyticsOpt = AnalyticsOpt.optOut;
@@ -134,13 +134,14 @@
}
@override
- Future sendScreenView(String viewName, {Map<String, String>? parameters}) {
+ Future<void> sendScreenView(String viewName,
+ {Map<String, String>? parameters}) {
var args = <String, String>{'cd': viewName, ...?parameters};
return _enqueuePayload('screenview', args);
}
@override
- Future sendEvent(String category, String action,
+ Future<void> sendEvent(String category, String action,
{String? label, int? value, Map<String, String>? parameters}) {
final args = <String, String>{
'ec': category,
@@ -154,13 +155,13 @@
}
@override
- Future sendSocial(String network, String action, String target) {
+ Future<void> sendSocial(String network, String action, String target) {
var args = <String, String>{'sn': network, 'sa': action, 'st': target};
return _enqueuePayload('social', args);
}
@override
- Future sendTiming(String variableName, int time,
+ Future<void> sendTiming(String variableName, int time,
{String? category, String? label}) {
var args = <String, String>{
'utv': variableName,
@@ -179,7 +180,7 @@
}
@override
- Future sendException(String description, {bool? fatal}) {
+ Future<void> sendException(String description, {bool? fatal}) {
// We trim exceptions to a max length; google analytics will apply it's own
// truncation, likely around 150 chars or so.
const maxExceptionLength = 1000;
@@ -234,14 +235,15 @@
void close() => postHandler.close();
@override
- String get clientId => properties['clientId'] ??= Uuid().generateV4();
+ String get clientId =>
+ (properties['clientId'] ??= Uuid().generateV4()) as String;
/// Send raw data to analytics. Callers should generally use one of the typed
/// methods (`sendScreenView`, `sendEvent`, ...).
///
/// Valid values for [hitType] are: 'pageview', 'screenview', 'event',
/// 'transaction', 'item', 'social', 'exception', and 'timing'.
- Future sendRaw(String hitType, Map<String, dynamic> args) {
+ Future<void> sendRaw(String hitType, Map<String, dynamic> args) {
return _enqueuePayload(hitType, args);
}
@@ -258,7 +260,7 @@
// TODO(sigurdm): Really all the 'send' methods should not return Futures
// there is not much point in waiting for it. Only [waitForLastPing].
final completer = Completer<void>();
- final eventArgs = <String, String>{
+ final eventArgs = <String, dynamic>{
...args,
..._variableMap,
'v': '1', // protocol version
@@ -284,7 +286,7 @@
} else if (!_isSendingScheduled) {
_isSendingScheduled = true;
// ignore: unawaited_futures
- Future.delayed(batchingDelay).then((value) {
+ Future<void>.delayed(batchingDelay).then((value) {
_isSendingScheduled = false;
_trySendBatches(completer);
});
@@ -299,7 +301,7 @@
static const _maxBytesPerBatch = 16000;
void _trySendBatches(Completer<void> completer) {
- final futures = <Future>[];
+ final futures = <Future<void>>[];
while (_batchedEvents.isNotEmpty) {
final batch = <String>[];
final totalLength = 0;
@@ -322,7 +324,7 @@
completer.complete(Future.wait(futures).then((_) {}));
}
- void _recordFuture(Future f) {
+ void _recordFuture(Future<void> f) {
_futures.add(f);
f.whenComplete(() => _futures.remove(f));
}
@@ -359,8 +361,8 @@
/// The `Future` from [sendPost] should complete when the operation is finished,
/// but failures to send the information should be silent.
abstract class PostHandler {
- Future sendPost(String url, List<String> batch);
- String encodeHit(Map<String, String> hit);
+ Future<void> sendPost(String url, List<String> batch);
+ String encodeHit(Map<String, dynamic> hit);
/// Free any used resources.
void close();
diff --git a/lib/src/usage_impl_html.dart b/lib/src/usage_impl_html.dart
index 59843b0..cd46c52 100644
--- a/lib/src/usage_impl_html.dart
+++ b/lib/src/usage_impl_html.dart
@@ -55,7 +55,7 @@
HtmlPostHandler({this.mockRequestor});
@override
- String encodeHit(Map<String, String> hit) {
+ String encodeHit(Map<String, dynamic> hit) {
var viewportWidth = document.documentElement!.clientWidth;
var viewportHeight = document.documentElement!.clientHeight;
return postEncode({...hit, 'vp': '${viewportWidth}x$viewportHeight'});
@@ -79,12 +79,12 @@
}
class HtmlPersistentProperties extends PersistentProperties {
- late final Map _map;
+ late final Map<String, dynamic> _map;
HtmlPersistentProperties(String name) : super(name) {
var str = window.localStorage[name];
if (str == null || str.isEmpty) str = '{}';
- _map = jsonDecode(str);
+ _map = jsonDecode(str) as Map<String, dynamic>;
}
@override
diff --git a/lib/src/usage_impl_io.dart b/lib/src/usage_impl_io.dart
index ca6980a..6284dfb 100644
--- a/lib/src/usage_impl_io.dart
+++ b/lib/src/usage_impl_io.dart
@@ -17,14 +17,14 @@
/// [analyticsUrl] is an optional replacement for the default Google Analytics
/// URL (`https://www.google-analytics.com/collect`).
///
-/// `trackingId`, `applicationName`, and `applicationVersion` values should be supplied.
-/// `analyticsUrl` is optional, and lets user's substitute their own analytics URL for
-/// the default.
+/// `trackingId`, `applicationName`, and `applicationVersion` values should be
+/// supplied. `analyticsUrl` is optional, and lets user's substitute their own
+/// analytics URL for the default.
///
/// `documentDirectory` is where the analytics settings are stored. It
-/// defaults to the user home directory. For regular `dart:io` apps this doesn't need to
-/// be supplied. For Flutter applications, you should pass in a value like
-/// `PathProvider.getApplicationDocumentsDirectory()`.
+/// defaults to the user home directory. For regular `dart:io` apps this doesn't
+/// need to be supplied. For Flutter applications, you should pass in a value
+/// like `PathProvider.getApplicationDocumentsDirectory()`.
///
/// [batchingDelay] is used to control batching behaviour. Events will be sent
/// batches of 20 after the duration is over from when the first message was
@@ -105,18 +105,18 @@
: _client = (client ?? HttpClient())..userAgent = createUserAgent();
@override
- String encodeHit(Map<String, String> hit) {
+ String encodeHit(Map<String, dynamic> hit) {
return postEncode(hit);
}
@override
- Future sendPost(String url, List<String> batch) async {
+ Future<void> sendPost(String url, List<String> batch) async {
var data = batch.join('\n');
try {
var req = await _client.postUrl(Uri.parse(url));
req.write(data);
var response = await req.close();
- await response.drain();
+ await response.drain<void>();
} on Exception {
// Catch errors that can happen during a request, but that we can't do
// anything about, e.g. a missing internet connection.
@@ -135,7 +135,7 @@
class IOPersistentProperties extends PersistentProperties {
late final File _file;
- late Map _map;
+ late Map<String, dynamic> _map;
IOPersistentProperties(String name, {String? documentDirPath}) : super(name) {
var fileName = '.${name.replaceAll(' ', '_')}';
@@ -179,7 +179,7 @@
try {
var contents = _file.readAsStringSync();
if (contents.isEmpty) contents = '{}';
- _map = jsonDecode(contents);
+ _map = jsonDecode(contents) as Map<String, dynamic>;
} catch (_) {
_map = {};
}
diff --git a/lib/usage.dart b/lib/usage.dart
index 1f1188a..addac23 100644
--- a/lib/usage.dart
+++ b/lib/usage.dart
@@ -72,14 +72,15 @@
///
/// [parameters] can be any analytics key/value pair. Useful
/// for custom dimensions, etc.
- Future sendScreenView(String viewName, {Map<String, String>? parameters});
+ Future<void> sendScreenView(String viewName,
+ {Map<String, String>? parameters});
/// Sends an Event hit to Google Analytics. [label] specifies the event label.
/// [value] specifies the event value. Values must be non-negative.
///
/// [parameters] can be any analytics key/value pair. Useful
/// for custom dimensions, etc.
- Future sendEvent(String category, String action,
+ Future<void> sendEvent(String category, String action,
{String? label, int? value, Map<String, String>? parameters});
/// Sends a Social hit to Google Analytics.
@@ -89,13 +90,13 @@
/// Google Plus when a user clicks the +1 button, the social action is 'plus'.
/// [target] specifies the target of a
/// social interaction. This value is typically a URL but can be any text.
- Future sendSocial(String network, String action, String target);
+ Future<void> sendSocial(String network, String action, String target);
/// Sends a Timing hit to Google Analytics. [variableName] specifies the
/// variable name of the timing. [time] specifies the user timing value (in
/// milliseconds). [category] specifies the category of the timing. [label]
/// specifies the label of the timing.
- Future sendTiming(String variableName, int time,
+ Future<void> sendTiming(String variableName, int time,
{String? category, String? label});
/// Start a timer. The time won't be calculated, and the analytics information
@@ -106,7 +107,7 @@
/// In order to avoid sending any personally identifying information, the
/// [description] field must not contain the exception message. In addition,
/// only the first 100 chars of the description will be sent.
- Future sendException(String description, {bool? fatal});
+ Future<void> sendException(String description, {bool? fatal});
/// Gets a session variable value.
dynamic getSessionValue(String param);
@@ -136,7 +137,7 @@
/// allows CLI apps to delay for a short time waiting for GA requests to
/// complete, and then do something like call `dart:io`'s `exit()` explicitly
/// themselves (or the [close] method below).
- Future waitForLastPing({Duration? timeout});
+ Future<void> waitForLastPing({Duration? timeout});
/// Free any used resources.
///
@@ -178,7 +179,7 @@
/// Finish the timer, calculate the elapsed time, and send the information to
/// analytics. Once this is called, any future invocations are no-ops.
- Future finish() {
+ Future<void> finish() {
if (_endMillis != null) return Future.value();
_endMillis = DateTime.now().millisecondsSinceEpoch;
@@ -220,14 +221,15 @@
String get clientId => '00000000-0000-4000-0000-000000000000';
@override
- Future sendScreenView(String viewName, {Map<String, String>? parameters}) {
+ Future<void> sendScreenView(String viewName,
+ {Map<String, String>? parameters}) {
parameters ??= <String, String>{};
parameters['viewName'] = viewName;
return _log('screenView', parameters);
}
@override
- Future sendEvent(String category, String action,
+ Future<void> sendEvent(String category, String action,
{String? label, int? value, Map<String, String>? parameters}) {
parameters ??= <String, String>{};
return _log(
@@ -237,11 +239,11 @@
}
@override
- Future sendSocial(String network, String action, String target) =>
+ Future<void> sendSocial(String network, String action, String target) =>
_log('social', {'network': network, 'action': action, 'target': target});
@override
- Future sendTiming(String variableName, int time,
+ Future<void> sendTiming(String variableName, int time,
{String? category, String? label}) {
return _log('timing', {
'variableName': variableName,
@@ -258,7 +260,7 @@
}
@override
- Future sendException(String description, {bool? fatal}) =>
+ Future<void> sendException(String description, {bool? fatal}) =>
_log('exception', {'description': description, 'fatal': fatal});
@override
@@ -271,12 +273,12 @@
Stream<Map<String, dynamic>> get onSend => _sendController.stream;
@override
- Future waitForLastPing({Duration? timeout}) => Future.value();
+ Future<void> waitForLastPing({Duration? timeout}) => Future.value();
@override
void close() {}
- Future _log(String hitType, Map m) {
+ Future<void> _log(String hitType, Map<String, dynamic> m) {
if (logCalls) {
print('analytics: $hitType $m');
}
diff --git a/pubspec.yaml b/pubspec.yaml
index e1f1053..4768a89 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -8,7 +8,7 @@
repository: https://github.com/dart-lang/usage
environment:
- sdk: '>=2.15.0 <3.0.0'
+ sdk: '>=2.17.0 <3.0.0'
dependencies:
meta: ^1.7.0
diff --git a/test/hit_types_test.dart b/test/hit_types_test.dart
index ecdce39..a8d8da9 100644
--- a/test/hit_types_test.dart
+++ b/test/hit_types_test.dart
@@ -105,7 +105,7 @@
var timer =
mock.startTimer('compile', category: 'Build', label: 'Compile');
- await Future.delayed(Duration(milliseconds: 20));
+ await Future<void>.delayed(Duration(milliseconds: 20));
await timer.finish();
expect(mock.mockPostHandler.sentValues, isNot(isEmpty));
@@ -117,7 +117,7 @@
var time = timer.currentElapsedMillis;
expect(time, greaterThan(10));
- await Future.delayed(Duration(milliseconds: 10));
+ await Future<void>.delayed(Duration(milliseconds: 10));
expect(timer.currentElapsedMillis, time);
});
});
diff --git a/test/src/common.dart b/test/src/common.dart
index b08d89b..aa440e4 100644
--- a/test/src/common.dart
+++ b/test/src/common.dart
@@ -39,10 +39,11 @@
void close() {}
@override
- String encodeHit(Map<String, String> hit) => jsonEncode(hit);
+ String encodeHit(Map<String, dynamic> hit) => jsonEncode(hit);
@override
- Future sendPost(String url, List<String> batch) => Completer().future;
+ Future<void> sendPost(String url, List<String> batch) =>
+ Completer<void>().future;
}
class MockProperties extends PersistentProperties {
@@ -68,7 +69,7 @@
List<String> sentValues = [];
@override
- Future sendPost(String url, List<String> batch) {
+ Future<void> sendPost(String url, List<String> batch) {
sentValues.addAll(batch);
return Future.value();
@@ -80,5 +81,5 @@
void close() {}
@override
- String encodeHit(Map<String, String> hit) => jsonEncode(hit);
+ String encodeHit(Map<String, dynamic> hit) => jsonEncode(hit);
}
diff --git a/test/usage_impl_test.dart b/test/usage_impl_test.dart
index 8b2739a..50924a8 100644
--- a/test/usage_impl_test.dart
+++ b/test/usage_impl_test.dart
@@ -34,7 +34,7 @@
expect(bucket.removeDrop(), false);
// TODO: Re-write to use package:fake_async.
- await Future.delayed(Duration(milliseconds: 1500));
+ await Future<void>.delayed(Duration(milliseconds: 1500));
expect(bucket.removeDrop(), true);
});
});
diff --git a/test/web_test.dart b/test/web_test.dart
index e2cabb2..5e6e891 100644
--- a/test/web_test.dart
+++ b/test/web_test.dart
@@ -62,7 +62,7 @@
class MockRequestor {
int sendCount = 0;
- Future<HttpRequest> request(String url, {String? method, sendData}) {
+ Future<HttpRequest> request(String url, {String? method, Object? sendData}) {
expect(url, isNotEmpty);
expect(method, isNotEmpty);
expect(sendData, isNotEmpty);