diff --git a/.travis.yml b/.travis.yml index 83a837c..5722c5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: dart sudo: false dart: - - stable - dev install: - gem install coveralls-lcov diff --git a/CHANGELOG.md b/CHANGELOG.md index e42859a..a5f2c99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 3.0.0-nullsafety + +* Migrate package to null-safe dart. + ### 2.2.1 * Add `operatingSystemVersion` diff --git a/.analysis_options b/analysis_options.yaml similarity index 89% rename from .analysis_options rename to analysis_options.yaml index 9f8e801..1b14e09 100644 --- a/.analysis_options +++ b/analysis_options.yaml @@ -1,8 +1,6 @@ analyzer: - language: - enableStrictCallChecks: true - enableSuperMixins: true - strong-mode: true + enable-experiment: + - non-nullable errors: # Allow having TODOs in the code todo: ignore @@ -40,7 +38,6 @@ linter: - await_only_futures - camel_case_types - constant_identifier_names - - control_flow_in_finally - empty_constructor_bodies - implementation_imports - library_names @@ -56,11 +53,9 @@ linter: - slash_for_doc_comments - sort_constructors_first - sort_unnamed_constructors_first - - super_goes_last - type_annotate_public_apis - type_init_formals - unawaited_futures - - unnecessary_brace_in_string_interp - unnecessary_getters_setters # === pub rules === diff --git a/dev/travis.sh b/dev/travis.sh index 866b361..722d4d8 100755 --- a/dev/travis.sh +++ b/dev/travis.sh @@ -15,7 +15,7 @@ echo "PASSED" # Make sure we pass the analyzer echo "Checking dartanalyzer..." -fails_analyzer="$(find lib test dev -name "*.dart" | xargs dartanalyzer --options .analysis_options)" +fails_analyzer="$(find lib test dev -name "*.dart" | xargs dartanalyzer --options analysis_options.yaml)" if [[ "$fails_analyzer" == *"[error]"* ]]; then echo "FAILED" echo "$fails_analyzer" @@ -27,4 +27,4 @@ echo "PASSED" set -e # Run the tests. -pub run test +pub run --enable-experiment=non-nullable test diff --git a/lib/platform.dart b/lib/platform.dart index 2770219..8110dd1 100644 --- a/lib/platform.dart +++ b/lib/platform.dart @@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// @dart=2.10 /// Core interfaces & classes. export 'src/interface/local_platform.dart'; export 'src/interface/platform.dart'; diff --git a/lib/src/interface/local_platform.dart b/lib/src/interface/local_platform.dart index 20b4bbe..f0c44bb 100644 --- a/lib/src/interface/local_platform.dart +++ b/lib/src/interface/local_platform.dart @@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// @dart=2.10 import 'dart:io' as io show Platform, stdin, stdout; import 'platform.dart'; @@ -42,10 +43,11 @@ class LocalPlatform extends Platform { List get executableArguments => io.Platform.executableArguments; @override - String get packageRoot => io.Platform.packageRoot; + String? get packageRoot => + io.Platform.packageRoot; // ignore: deprecated_member_use @override - String get packageConfig => io.Platform.packageConfig; + String? get packageConfig => io.Platform.packageConfig; @override String get version => io.Platform.version; diff --git a/lib/src/interface/platform.dart b/lib/src/interface/platform.dart index afc527a..ee7d28e 100644 --- a/lib/src/interface/platform.dart +++ b/lib/src/interface/platform.dart @@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// @dart=2.10 import 'dart:convert'; /// Provides API parity with the `Platform` class in `dart:io`, but using @@ -101,14 +102,15 @@ abstract class Platform { /// Dart packages are looked up. /// /// If there is no `--package-root` flag, `null` is returned. - String get packageRoot; + @deprecated + String? get packageRoot; /// The value of the `--packages` flag passed to the executable /// used to run the script in this isolate. This is the configuration which /// specifies how Dart packages are looked up. /// /// If there is no `--packages` flag, `null` is returned. - String get packageConfig; + String? get packageConfig; /// The version of the current Dart runtime. /// @@ -139,7 +141,8 @@ abstract class Platform { 'resolvedExecutable': resolvedExecutable, 'script': script.toString(), 'executableArguments': executableArguments, - 'packageRoot': packageRoot, + 'packageRoot': + packageRoot, // ignore: deprecated_member_use_from_same_package 'packageConfig': packageConfig, 'version': version, 'stdinSupportsAnsi': stdinSupportsAnsi, diff --git a/lib/src/testing/fake_platform.dart b/lib/src/testing/fake_platform.dart index 0d868bd..0af10bc 100644 --- a/lib/src/testing/fake_platform.dart +++ b/lib/src/testing/fake_platform.dart @@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// @dart=2.10 import 'dart:convert'; import '../interface/platform.dart'; @@ -11,46 +12,60 @@ class FakePlatform extends Platform { /// Creates a new [FakePlatform] with the specified properties. /// /// Unspecified properties will *not* be assigned default values (they will - /// remain `null`). + /// remain `null`). If an unset non-null value is read, a [StateError] will + /// be thrown instead of returnin `null`. FakePlatform({ - this.numberOfProcessors, - this.pathSeparator, - this.operatingSystem, - this.operatingSystemVersion, - this.localHostname, - this.environment, - this.executable, - this.resolvedExecutable, - this.script, - this.executableArguments, + int? numberOfProcessors, + String? pathSeparator, + String? operatingSystem, + String? operatingSystemVersion, + String? localHostname, + Map? environment, + String? executable, + String? resolvedExecutable, + Uri? script, + List? executableArguments, this.packageRoot, this.packageConfig, - this.version, - this.stdinSupportsAnsi, - this.stdoutSupportsAnsi, - this.localeName, - }); + String? version, + bool? stdinSupportsAnsi, + bool? stdoutSupportsAnsi, + String? localeName, + }) : _numberOfProcessors = numberOfProcessors, + _pathSeparator = pathSeparator, + _operatingSystem = operatingSystem, + _operatingSystemVersion = operatingSystemVersion, + _localHostname = localHostname, + _environment = environment, + _executable = executable, + _resolvedExecutable = resolvedExecutable, + _script = script, + _executableArguments = executableArguments, + _version = version, + _stdinSupportsAnsi = stdinSupportsAnsi, + _stdoutSupportsAnsi = stdoutSupportsAnsi, + _localeName = localeName; /// Creates a new [FakePlatform] with properties whose initial values mirror /// the specified [platform]. FakePlatform.fromPlatform(Platform platform) - : numberOfProcessors = platform.numberOfProcessors, - pathSeparator = platform.pathSeparator, - operatingSystem = platform.operatingSystem, - operatingSystemVersion = platform.operatingSystemVersion, - localHostname = platform.localHostname, - environment = new Map.from(platform.environment), - executable = platform.executable, - resolvedExecutable = platform.resolvedExecutable, - script = platform.script, - executableArguments = - new List.from(platform.executableArguments), - packageRoot = platform.packageRoot, + : _numberOfProcessors = platform.numberOfProcessors, + _pathSeparator = platform.pathSeparator, + _operatingSystem = platform.operatingSystem, + _operatingSystemVersion = platform.operatingSystemVersion, + _localHostname = platform.localHostname, + _environment = Map.from(platform.environment), + _executable = platform.executable, + _resolvedExecutable = platform.resolvedExecutable, + _script = platform.script, + _executableArguments = List.from(platform.executableArguments), + packageRoot = platform + .packageRoot, // ignore: deprecated_member_use_from_same_package packageConfig = platform.packageConfig, - version = platform.version, - stdinSupportsAnsi = platform.stdinSupportsAnsi, - stdoutSupportsAnsi = platform.stdoutSupportsAnsi, - localeName = platform.localeName; + _version = platform.version, + _stdinSupportsAnsi = platform.stdinSupportsAnsi, + _stdoutSupportsAnsi = platform.stdoutSupportsAnsi, + _localeName = platform.localeName; /// Creates a new [FakePlatform] with properties extracted from the encoded /// JSON string. @@ -80,50 +95,72 @@ class FakePlatform extends Platform { } @override - int numberOfProcessors; + int get numberOfProcessors => _throwIfNull(_numberOfProcessors); + int? _numberOfProcessors; @override - String pathSeparator; + String get pathSeparator => _throwIfNull(_pathSeparator); + String? _pathSeparator; @override - String operatingSystem; + String get operatingSystem => _throwIfNull(_operatingSystem); + String? _operatingSystem; @override - String operatingSystemVersion; + String get operatingSystemVersion => _throwIfNull(_operatingSystemVersion); + String? _operatingSystemVersion; @override - String localHostname; + String get localHostname => _throwIfNull(_localHostname); + String? _localHostname; @override - Map environment; + Map get environment => _throwIfNull(_environment); + Map? _environment; @override - String executable; + String get executable => _throwIfNull(_executable); + String? _executable; @override - String resolvedExecutable; + String get resolvedExecutable => _throwIfNull(_resolvedExecutable); + String? _resolvedExecutable; @override - Uri script; + Uri get script => _throwIfNull(_script); + Uri? _script; @override - List executableArguments; + List get executableArguments => _throwIfNull(_executableArguments); + List? _executableArguments; @override - String packageRoot; + String? packageRoot; @override - String packageConfig; + String? packageConfig; @override - String version; + String get version => _throwIfNull(_version); + String? _version; @override - bool stdinSupportsAnsi; + bool get stdinSupportsAnsi => _throwIfNull(_stdinSupportsAnsi); + bool? _stdinSupportsAnsi; @override - bool stdoutSupportsAnsi; + bool get stdoutSupportsAnsi => _throwIfNull(_stdoutSupportsAnsi); + bool? _stdoutSupportsAnsi; @override - String localeName; + String get localeName => _throwIfNull(_localeName); + String? _localeName; + + T _throwIfNull(T? value) { + if (value == null) { + throw StateError( + 'Tried to read property of FakePlatform but it was unset.'); + } + return value; + } } diff --git a/pubspec.yaml b/pubspec.yaml index 1e3c40a..6f22a33 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,5 @@ name: platform -version: 2.2.1 -authors: -- Todd Volkert +version: 3.0.0-nullsafety description: A pluggable, mockable platform abstraction for Dart. homepage: https://github.com/google/platform.dart @@ -9,4 +7,4 @@ dev_dependencies: test: ^1.0.0 environment: - sdk: '>=1.24.0-dev.0.0 <3.0.0' + sdk: '>=2.9.0 <3.0.0' diff --git a/test/fake_platform_test.dart b/test/fake_platform_test.dart index 90d8209..0ef8d23 100644 --- a/test/fake_platform_test.dart +++ b/test/fake_platform_test.dart @@ -18,7 +18,9 @@ void _expectPlatformsEqual(Platform actual, Platform expected) { expect(actual.resolvedExecutable, expected.resolvedExecutable); expect(actual.script, expected.script); expect(actual.executableArguments, expected.executableArguments); - expect(actual.packageRoot, expected.packageRoot); + expect( + actual.packageRoot, // ignore: deprecated_member_use_from_same_package + expected.packageRoot); // ignore: deprecated_member_use_from_same_package expect(actual.packageConfig, expected.packageConfig); expect(actual.version, expected.version); expect(actual.localeName, expected.localeName); @@ -87,4 +89,21 @@ void main() { }); }); }); + + test('Throws when unset non-null values are read', () { + final FakePlatform platform = FakePlatform(); + + expect(() => platform.numberOfProcessors, throwsA(isStateError)); + expect(() => platform.pathSeparator, throwsA(isStateError)); + expect(() => platform.operatingSystem, throwsA(isStateError)); + expect(() => platform.operatingSystemVersion, throwsA(isStateError)); + expect(() => platform.localHostname, throwsA(isStateError)); + expect(() => platform.environment, throwsA(isStateError)); + expect(() => platform.executable, throwsA(isStateError)); + expect(() => platform.resolvedExecutable, throwsA(isStateError)); + expect(() => platform.script, throwsA(isStateError)); + expect(() => platform.executableArguments, throwsA(isStateError)); + expect(() => platform.version, throwsA(isStateError)); + expect(() => platform.localeName, throwsA(isStateError)); + }); }