Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[path_provider] Update to stable NNBD #3582

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions packages/path_provider/path_provider/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
## 2.0.0-nullsafety.1

* Require latest path_provider_windows to avoid potential issues
with breaking changes in `ffi` and `win32`.

## 2.0.0-nullsafety
## 2.0.0

* Migrate to null safety.
* BREAKING CHANGE: Path accessors that return non-nullable results will throw
a `MissingPlatformDirectoryException` if the platform implementation is unable
to get the corresponding directory (except on platforms where the method is
explicitly unsupported, where they will continue to throw `UnsupportedError`).

## 1.6.28

Expand Down
4 changes: 2 additions & 2 deletions packages/path_provider/path_provider/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ dev_dependencies:
path: ../../../integration_test
flutter_driver:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0

flutter:
uses-material-design: true

environment:
sdk: ">=2.12.0-0 <3.0.0"
sdk: ">=2.12.0-259.9.beta <3.0.0"
flutter: ">=1.12.13+hotfix.5"
52 changes: 44 additions & 8 deletions packages/path_provider/path_provider/lib/path_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,27 @@ set disablePathProviderPlatformOverride(bool override) {}

bool _manualDartRegistrationNeeded = true;

/// An exception thrown when a directory that should always be available on
/// the current platform cannot be obtained.
class MissingPlatformDirectoryException implements Exception {
/// Creates a new exception
MissingPlatformDirectoryException(this.message, {this.details});

/// The explanation of the exception.
final String message;

/// Added details, if any.
///
/// E.g., an error object from the platform implementation.
final Object? details;

@override
String toString() {
String detailsAddition = details == null ? '' : ': $details';
return 'MissingPlatformDirectoryException($message)$detailsAddition';
}
}

PathProviderPlatform get _platform {
// This is to manually endorse Dart implementations until automatic
// registration of Dart plugins is implemented. For details see
Expand Down Expand Up @@ -51,10 +72,14 @@ PathProviderPlatform get _platform {
/// On iOS, this uses the `NSCachesDirectory` API.
///
/// On Android, this uses the `getCacheDir` API on the context.
Future<Directory?> getTemporaryDirectory() async {
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// provide the directory.
Future<Directory> getTemporaryDirectory() async {
final String? path = await _platform.getTemporaryPath();
if (path == null) {
return null;
throw MissingPlatformDirectoryException(
'Unable to get temporary directory');
}
return Directory(path);
}
Expand All @@ -69,10 +94,14 @@ Future<Directory?> getTemporaryDirectory() async {
/// If this directory does not exist, it is created automatically.
///
/// On Android, this function uses the `getFilesDir` API on the context.
Future<Directory?> getApplicationSupportDirectory() async {
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// provide the directory.
Future<Directory> getApplicationSupportDirectory() async {
final String? path = await _platform.getApplicationSupportPath();
if (path == null) {
return null;
throw MissingPlatformDirectoryException(
'Unable to get application support directory');
}

return Directory(path);
Expand All @@ -83,10 +112,13 @@ Future<Directory?> getApplicationSupportDirectory() async {
///
/// On Android, this function throws an [UnsupportedError] as no equivalent
/// path exists.
Future<Directory?> getLibraryDirectory() async {
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// provide the directory on a supported platform.
Future<Directory> getLibraryDirectory() async {
final String? path = await _platform.getLibraryPath();
if (path == null) {
return null;
throw MissingPlatformDirectoryException('Unable to get library directory');
}
return Directory(path);
}
Expand All @@ -100,10 +132,14 @@ Future<Directory?> getLibraryDirectory() async {
/// On Android, this uses the `getDataDirectory` API on the context. Consider
/// using [getExternalStorageDirectory] instead if data is intended to be visible
/// to the user.
Future<Directory?> getApplicationDocumentsDirectory() async {
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// provide the directory.
Future<Directory> getApplicationDocumentsDirectory() async {
final String? path = await _platform.getApplicationDocumentsPath();
if (path == null) {
return null;
throw MissingPlatformDirectoryException(
'Unable to get application documents directory');
}
return Directory(path);
}
Expand Down
18 changes: 9 additions & 9 deletions packages/path_provider/path_provider/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: path_provider
description: Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories.
homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider
version: 2.0.0-nullsafety.1
version: 2.0.0

flutter:
plugin:
Expand All @@ -21,10 +21,10 @@ flutter:
dependencies:
flutter:
sdk: flutter
path_provider_platform_interface: ^2.0.0-nullsafety
path_provider_macos: ^0.0.5-nullsafety
path_provider_linux: ^0.2.0-nullsafety
path_provider_windows: ^0.1.0-nullsafety.3
path_provider_platform_interface: ^2.0.0
path_provider_macos: ^2.0.0
path_provider_linux: ^2.0.0
path_provider_windows: ^2.0.0

dev_dependencies:
integration_test:
Expand All @@ -33,10 +33,10 @@ dev_dependencies:
sdk: flutter
flutter_driver:
sdk: flutter
pedantic: ^1.10.0-nullsafety
mockito: ^5.0.0-nullsafety.0
plugin_platform_interface: ^1.1.0-nullsafety
pedantic: ^1.10.0
plugin_platform_interface: ">=1.0.0 <3.0.0"
test: ^1.16.0

environment:
sdk: ">=2.12.0-0 <3.0.0"
sdk: ">=2.12.0-259.9.beta <3.0.0"
flutter: ">=1.12.13+hotfix.5"
127 changes: 105 additions & 22 deletions packages/path_provider/path_provider/test/path_provider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import 'dart:io' show Directory;
import 'dart:async';

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:test/fake.dart';

const String kTemporaryPath = 'temporaryPath';
const String kApplicationSupportPath = 'applicationSupportPath';
Expand All @@ -20,31 +20,30 @@ const String kExternalCachePath = 'externalCachePath';
const String kExternalStoragePath = 'externalStoragePath';

void main() {
group('PathProvider', () {
TestWidgetsFlutterBinding.ensureInitialized();

TestWidgetsFlutterBinding.ensureInitialized();
group('PathProvider full implementation', () {
setUp(() async {
PathProviderPlatform.instance = MockPathProviderPlatform();
PathProviderPlatform.instance = FakePathProviderPlatform();
});

test('getTemporaryDirectory', () async {
Directory? result = await getTemporaryDirectory();
expect(result?.path, kTemporaryPath);
Directory result = await getTemporaryDirectory();
expect(result.path, kTemporaryPath);
});

test('getApplicationSupportDirectory', () async {
Directory? result = await getApplicationSupportDirectory();
expect(result?.path, kApplicationSupportPath);
Directory result = await getApplicationSupportDirectory();
expect(result.path, kApplicationSupportPath);
});

test('getLibraryDirectory', () async {
Directory? result = await getLibraryDirectory();
expect(result?.path, kLibraryPath);
Directory result = await getLibraryDirectory();
expect(result.path, kLibraryPath);
});

test('getApplicationDocumentsDirectory', () async {
Directory? result = await getApplicationDocumentsDirectory();
expect(result?.path, kApplicationDocumentsPath);
Directory result = await getApplicationDocumentsDirectory();
expect(result.path, kApplicationDocumentsPath);
});

test('getExternalStorageDirectory', () async {
Expand All @@ -69,42 +68,126 @@ void main() {
expect(result?.path, kDownloadsPath);
});
});

group('PathProvider null implementation', () {
setUp(() async {
PathProviderPlatform.instance = AllNullFakePathProviderPlatform();
});

test('getTemporaryDirectory throws on null', () async {
expect(getTemporaryDirectory(),
throwsA(isA<MissingPlatformDirectoryException>()));
});

test('getApplicationSupportDirectory throws on null', () async {
expect(getApplicationSupportDirectory(),
throwsA(isA<MissingPlatformDirectoryException>()));
});

test('getLibraryDirectory throws on null', () async {
expect(getLibraryDirectory(),
throwsA(isA<MissingPlatformDirectoryException>()));
});

test('getApplicationDocumentsDirectory throws on null', () async {
expect(getApplicationDocumentsDirectory(),
throwsA(isA<MissingPlatformDirectoryException>()));
});

test('getExternalStorageDirectory passes null through', () async {
Directory? result = await getExternalStorageDirectory();
expect(result, isNull);
});

test('getExternalCacheDirectories passes null through', () async {
List<Directory>? result = await getExternalCacheDirectories();
expect(result, isNull);
});

test('getExternalStorageDirectories passes null through', () async {
List<Directory>? result = await getExternalStorageDirectories();
expect(result, isNull);
});

test('getDownloadsDirectory passses null through', () async {
Directory? result = await getDownloadsDirectory();
expect(result, isNull);
});
});
}

class MockPathProviderPlatform extends Mock
class FakePathProviderPlatform extends Fake
with MockPlatformInterfaceMixin
implements PathProviderPlatform {
Future<String> getTemporaryPath() async {
Future<String?> getTemporaryPath() async {
return kTemporaryPath;
}

Future<String> getApplicationSupportPath() async {
Future<String?> getApplicationSupportPath() async {
return kApplicationSupportPath;
}

Future<String> getLibraryPath() async {
Future<String?> getLibraryPath() async {
return kLibraryPath;
}

Future<String> getApplicationDocumentsPath() async {
Future<String?> getApplicationDocumentsPath() async {
return kApplicationDocumentsPath;
}

Future<String> getExternalStoragePath() async {
Future<String?> getExternalStoragePath() async {
return kExternalStoragePath;
}

Future<List<String>> getExternalCachePaths() async {
Future<List<String>?> getExternalCachePaths() async {
return <String>[kExternalCachePath];
}

Future<List<String>> getExternalStoragePaths({
Future<List<String>?> getExternalStoragePaths({
StorageDirectory? type,
}) async {
return <String>[kExternalStoragePath];
}

Future<String> getDownloadsPath() async {
Future<String?> getDownloadsPath() async {
return kDownloadsPath;
}
}

class AllNullFakePathProviderPlatform extends Fake
with MockPlatformInterfaceMixin
implements PathProviderPlatform {
Future<String?> getTemporaryPath() async {
return null;
}

Future<String?> getApplicationSupportPath() async {
return null;
}

Future<String?> getLibraryPath() async {
return null;
}

Future<String?> getApplicationDocumentsPath() async {
return null;
}

Future<String?> getExternalStoragePath() async {
return null;
}

Future<List<String>?> getExternalCachePaths() async {
return null;
}

Future<List<String>?> getExternalStoragePaths({
StorageDirectory? type,
}) async {
return null;
}

Future<String?> getDownloadsPath() async {
return null;
}
}