Skip to content

Commit 31923c8

Browse files
[path_provider] Migrate path_provider_windows to nullsafety (flutter#3410)
Migrates path_provider_windows to null-safety. Part of flutter#70229
1 parent f302473 commit 31923c8

File tree

5 files changed

+54
-42
lines changed

5 files changed

+54
-42
lines changed

packages/path_provider/path_provider_windows/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.1.0-nullsafety
2+
3+
* Migrate to null safety
4+
15
## 0.0.4+4
26

37
* Update Flutter SDK constraint.

packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,19 @@ import 'folders.dart';
2222
class VersionInfoQuerier {
2323
/// Returns the value for [key] in [versionInfo]s English strings section, or
2424
/// null if there is no such entry, or if versionInfo is null.
25-
getStringValue(Pointer<Uint8> versionInfo, key) {
25+
getStringValue(Pointer<Uint8>? versionInfo, key) {
2626
if (versionInfo == null) {
2727
return null;
2828
}
2929
const kEnUsLanguageCode = '040904e4';
3030
final keyPath = TEXT('\\StringFileInfo\\$kEnUsLanguageCode\\$key');
3131
final length = allocate<Uint32>();
32-
final valueAddress = allocate<IntPtr>();
32+
final valueAddress = allocate<Pointer<Utf16>>();
3333
try {
3434
if (VerQueryValue(versionInfo, keyPath, valueAddress, length) == 0) {
3535
return null;
3636
}
37-
return Pointer<Utf16>.fromAddress(valueAddress.value)
38-
.unpackString(length.value);
37+
return valueAddress.value.unpackString(length.value);
3938
} finally {
4039
free(keyPath);
4140
free(length);
@@ -54,7 +53,7 @@ class PathProviderWindows extends PathProviderPlatform {
5453

5554
/// This is typically the same as the TMP environment variable.
5655
@override
57-
Future<String> getTemporaryPath() async {
56+
Future<String?> getTemporaryPath() async {
5857
final buffer = allocate<Uint16>(count: MAX_PATH + 1).cast<Utf16>();
5958
String path;
6059

@@ -88,7 +87,7 @@ class PathProviderWindows extends PathProviderPlatform {
8887
}
8988

9089
@override
91-
Future<String> getApplicationSupportPath() async {
90+
Future<String?> getApplicationSupportPath() async {
9291
final appDataRoot = await getPath(WindowsKnownFolder.RoamingAppData);
9392
final directory = Directory(
9493
path.join(appDataRoot, _getApplicationSpecificSubdirectory()));
@@ -105,25 +104,23 @@ class PathProviderWindows extends PathProviderPlatform {
105104
}
106105

107106
@override
108-
Future<String> getApplicationDocumentsPath() =>
107+
Future<String?> getApplicationDocumentsPath() =>
109108
getPath(WindowsKnownFolder.Documents);
110109

111110
@override
112-
Future<String> getDownloadsPath() => getPath(WindowsKnownFolder.Downloads);
111+
Future<String?> getDownloadsPath() => getPath(WindowsKnownFolder.Downloads);
113112

114113
/// Retrieve any known folder from Windows.
115114
///
116115
/// folderID is a GUID that represents a specific known folder ID, drawn from
117116
/// [WindowsKnownFolder].
118117
Future<String> getPath(String folderID) {
119-
final pathPtrPtr = allocate<IntPtr>();
120-
Pointer<Utf16> pathPtr;
118+
final pathPtrPtr = allocate<Pointer<Utf16>>();
119+
final Pointer<GUID> knownFolderID = calloc<GUID>()..setGUID(folderID);
121120

122121
try {
123-
GUID knownFolderID = GUID.fromString(folderID);
124-
125122
final hr = SHGetKnownFolderPath(
126-
knownFolderID.addressOf, // ignore: deprecated_member_use
123+
knownFolderID,
127124
KF_FLAG_DEFAULT,
128125
NULL,
129126
pathPtrPtr,
@@ -135,12 +132,11 @@ class PathProviderWindows extends PathProviderPlatform {
135132
}
136133
}
137134

138-
pathPtr = Pointer<Utf16>.fromAddress(pathPtrPtr.value);
139-
final path = pathPtr.unpackString(MAX_PATH);
135+
final path = pathPtrPtr.value.unpackString(MAX_PATH);
140136
return Future.value(path);
141137
} finally {
142-
CoTaskMemFree(pathPtr.cast());
143138
free(pathPtrPtr);
139+
free(knownFolderID);
144140
}
145141
}
146142

@@ -155,13 +151,13 @@ class PathProviderWindows extends PathProviderPlatform {
155151
/// - If the product name isn't there, it will use the exe's filename (without
156152
/// extension).
157153
String _getApplicationSpecificSubdirectory() {
158-
String companyName;
159-
String productName;
154+
String? companyName;
155+
String? productName;
160156

161157
final Pointer<Utf16> moduleNameBuffer =
162158
allocate<Uint16>(count: MAX_PATH + 1).cast<Utf16>();
163159
final Pointer<Uint32> unused = allocate<Uint32>();
164-
Pointer<Uint8> infoBuffer;
160+
Pointer<Uint8>? infoBuffer;
165161
try {
166162
// Get the module name.
167163
final moduleNameLength = GetModuleFileName(0, moduleNameBuffer, MAX_PATH);
@@ -207,7 +203,7 @@ class PathProviderWindows extends PathProviderPlatform {
207203
/// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
208204
///
209205
/// If after sanitizing the string is empty, returns null.
210-
String _sanitizedDirectoryName(String rawString) {
206+
String? _sanitizedDirectoryName(String? rawString) {
211207
if (rawString == null) {
212208
return null;
213209
}

packages/path_provider/path_provider_windows/lib/src/path_provider_windows_stub.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class PathProviderWindows extends PathProviderPlatform {
1919
}
2020

2121
/// Stub; see comment on VersionInfoQuerier.
22-
VersionInfoQuerier versionInfoQuerier;
22+
VersionInfoQuerier versionInfoQuerier = VersionInfoQuerier();
2323

2424
/// Match PathProviderWindows so that the analyzer won't report invalid
2525
/// overrides if tests provide fake PathProviderWindows implementations.
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: path_provider_windows
22
description: Windows implementation of the path_provider plugin
33
homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows
4-
version: 0.0.4+4
4+
version: 0.1.0-nullsafety
55

66
flutter:
77
plugin:
@@ -11,19 +11,19 @@ flutter:
1111
pluginClass: none
1212

1313
dependencies:
14-
path_provider_platform_interface: ^1.0.3
15-
meta: ^1.0.5
16-
path: ^1.6.4
14+
path_provider_platform_interface: ^2.0.0-nullsafety
15+
meta: ^1.3.0-nullsafety.6
16+
path: ^1.8.0-nullsafety.3
1717
flutter:
1818
sdk: flutter
19-
ffi: ^0.1.3
20-
win32: ^1.7.1
19+
ffi: ^0.2.0-nullsafety.1
20+
win32: ^2.0.0-nullsafety.8
2121

2222
dev_dependencies:
2323
flutter_test:
2424
sdk: flutter
25-
pedantic: ^1.8.0
25+
pedantic: ^1.10.0-nullsafety.3
2626

2727
environment:
28-
sdk: ">=2.1.0 <3.0.0"
28+
sdk: '>=2.12.0-0 <3.0.0'
2929
flutter: ">=1.12.13+hotfix.4"

packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class FakeVersionInfoQuerier implements VersionInfoQuerier {
1313

1414
final Map<String, String> responses;
1515

16-
getStringValue(Pointer<Uint8> versionInfo, key) => responses[key];
16+
getStringValue(Pointer<Uint8>? versionInfo, key) => responses[key];
1717
}
1818

1919
void main() {
@@ -40,8 +40,11 @@ void main() {
4040
'ProductName': 'Amazing App',
4141
});
4242
final path = await pathProvider.getApplicationSupportPath();
43-
expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App'));
44-
expect(Directory(path).existsSync(), isTrue);
43+
expect(path, isNotNull);
44+
if (path != null) {
45+
expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App'));
46+
expect(Directory(path).existsSync(), isTrue);
47+
}
4548
}, skip: !Platform.isWindows);
4649

4750
test('getApplicationSupportPath with missing company', () async {
@@ -50,8 +53,11 @@ void main() {
5053
'ProductName': 'Amazing App',
5154
});
5255
final path = await pathProvider.getApplicationSupportPath();
53-
expect(path, endsWith(r'AppData\Roaming\Amazing App'));
54-
expect(Directory(path).existsSync(), isTrue);
56+
expect(path, isNotNull);
57+
if (path != null) {
58+
expect(path, endsWith(r'AppData\Roaming\Amazing App'));
59+
expect(Directory(path).existsSync(), isTrue);
60+
}
5561
}, skip: !Platform.isWindows);
5662

5763
test('getApplicationSupportPath with problematic values', () async {
@@ -61,12 +67,15 @@ void main() {
6167
'ProductName': r'A"/Terrible\|App?*Name',
6268
});
6369
final path = await pathProvider.getApplicationSupportPath();
64-
expect(
65-
path,
66-
endsWith(r'AppData\Roaming\'
67-
r'A _Bad_ Company_ Name\'
68-
r'A__Terrible__App__Name'));
69-
expect(Directory(path).existsSync(), isTrue);
70+
expect(path, isNotNull);
71+
if (path != null) {
72+
expect(
73+
path,
74+
endsWith(r'AppData\Roaming\'
75+
r'A _Bad_ Company_ Name\'
76+
r'A__Terrible__App__Name'));
77+
expect(Directory(path).existsSync(), isTrue);
78+
}
7079
}, skip: !Platform.isWindows);
7180

7281
test('getApplicationSupportPath with a completely invalid company', () async {
@@ -76,8 +85,11 @@ void main() {
7685
'ProductName': r'Amazing App',
7786
});
7887
final path = await pathProvider.getApplicationSupportPath();
79-
expect(path, endsWith(r'AppData\Roaming\Amazing App'));
80-
expect(Directory(path).existsSync(), isTrue);
88+
expect(path, isNotNull);
89+
if (path != null) {
90+
expect(path, endsWith(r'AppData\Roaming\Amazing App'));
91+
expect(Directory(path).existsSync(), isTrue);
92+
}
8193
}, skip: !Platform.isWindows);
8294

8395
test('getApplicationSupportPath with very long app name', () async {

0 commit comments

Comments
 (0)