Skip to content

Commit f234742

Browse files
authored
Merge pull request #28 from Workiva/null_safety
Migrate to null safety
2 parents 18a6988 + 18915e3 commit f234742

19 files changed

+89
-86
lines changed

.github/workflows/dart_ci.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515
strategy:
1616
fail-fast: false
1717
matrix:
18-
sdk: [ stable, 2.13.4 ]
18+
sdk: [ 2.18.7, stable ]
1919
steps:
2020
- uses: actions/checkout@v2
21-
- uses: dart-lang/setup-dart@v0.2
21+
- uses: dart-lang/setup-dart@v1
2222
with:
2323
sdk: ${{ matrix.sdk }}
2424

@@ -27,11 +27,10 @@ jobs:
2727

2828
- name: Formatting
2929
run: dart format --output=none --set-exit-if-changed .
30-
if: always() && ${{ matrix.sdk }} == 'stable'
30+
if: ${{ matrix.sdk }} == '2.18.7'
3131

3232
- name: Analysis
3333
run: dart analyze
3434

3535
- name: Tests
3636
run: dart test --chain-stack-traces
37-
if: ${{ matrix.sdk == '2.13.4' }}

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM google/dart:2.13
1+
FROM drydock-prod.workiva.net/workiva/dart2_base_image:1
22
WORKDIR /build/
33
ADD pubspec.yaml .
44
RUN dart pub get

analysis_options.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
include: package:pedantic/analysis_options.yaml
1+
include: package:lints/recommended.yaml

lib/src/command_runner.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
14+
import 'dart:async';
1515
import 'package:args/args.dart';
1616
import 'package:args/command_runner.dart';
1717
import 'package:logging/logging.dart';
@@ -33,11 +33,11 @@ class WebdevProxy extends CommandRunner<int> {
3333
@override
3434
Future<int> run(Iterable<String> args) async {
3535
// The help command returns null, so return success code in that case.
36-
return await super.run(args) ?? 0;
36+
return (await super.run(args)) ?? 0;
3737
}
3838

3939
@override
40-
Future<int> runCommand(ArgResults topLevelResults) async {
40+
Future<int?> runCommand(ArgResults topLevelResults) async {
4141
final verbose = topLevelResults[verboseFlag] == true;
4242
Logger.root.level = verbose ? Level.ALL : Level.INFO;
4343
Logger.root.onRecord.listen(stdIOLogListener(verbose: verbose));

lib/src/logging.dart

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ const _logSuffix = '\n';
2828

2929
final Logger log = Logger('Proxy');
3030

31-
StringBuffer colorLog(LogRecord record, {bool verbose}) {
32-
verbose ??= false;
33-
31+
StringBuffer colorLog(LogRecord record, {bool verbose = false}) {
3432
AnsiCode color;
3533
if (record.level < Level.WARNING) {
3634
color = cyan;
@@ -44,13 +42,13 @@ StringBuffer colorLog(LogRecord record, {bool verbose}) {
4442
final lines = <Object>[
4543
'$eraseLine$level ${_loggerName(record, verbose)}${record.message}'
4644
];
47-
48-
if (record.error != null) {
49-
lines.add(record.error);
45+
var error = record.error;
46+
if (error != null) {
47+
lines.add(error);
5048
}
5149

5250
if (record.stackTrace != null && verbose) {
53-
final trace = Trace.from(record.stackTrace).terse;
51+
final trace = Trace.from(record.stackTrace!).terse;
5452
lines.add(trace);
5553
}
5654

@@ -130,7 +128,7 @@ T logTimedSync<T>(
130128
return result;
131129
}
132130

133-
Function(LogRecord) stdIOLogListener({bool verbose}) =>
131+
Function(LogRecord) stdIOLogListener({bool verbose = false}) =>
134132
(record) => io.stdout.write(colorLog(record, verbose: verbose));
135133

136134
String _loggerName(LogRecord record, bool verbose) {

lib/src/serve_command.dart

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import 'dart:io';
1818
import 'package:args/command_runner.dart';
1919
import 'package:io/ansi.dart';
2020
import 'package:io/io.dart';
21-
import 'package:pedantic/pedantic.dart';
2221

2322
import 'package:webdev_proxy/src/command_runner.dart';
2423
import 'package:webdev_proxy/src/command_utils.dart';
@@ -52,15 +51,15 @@ class ServeCommand extends Command<int> {
5251
'[-- [webdev serve arguments]]';
5352

5453
@override
55-
String get usageFooter => _webdevCompatibilityHelp;
54+
String? get usageFooter => _webdevCompatibilityHelp;
5655

5756
@override
5857
String get name => 'serve';
5958

6059
bool get _canUseWebdev => !_missingWebdev && _hasCompatibleWebdev;
6160

6261
bool get _hasCompatibleWebdev =>
63-
webdevCompatibility.allows(getGlobalWebdevVersion());
62+
webdevCompatibility.allows(getGlobalWebdevVersion()!);
6463

6564
bool get _missingWebdev => getGlobalWebdevVersion() == null;
6665

@@ -78,7 +77,7 @@ class ServeCommand extends Command<int> {
7877
}
7978
}
8079

81-
String get _webdevCompatibilityHelp {
80+
String? get _webdevCompatibilityHelp {
8281
if (_missingWebdev) {
8382
return red.wrap(
8483
'This command requires that `webdev` be activated globally.\n'
@@ -109,19 +108,19 @@ class ServeCommand extends Command<int> {
109108
//
110109
// To enforce this, we validate that [argResults.rest] is exactly equal to
111110
// all the arguments after the `--`.
112-
assertNoPositionalArgsBeforeSeparator(name, argResults, usageException);
111+
assertNoPositionalArgsBeforeSeparator(name, argResults!, usageException);
113112

114113
final exitCodeCompleter = Completer<int>();
115114
var interruptReceived = false;
116115
final proxies = <WebdevProxyServer>[];
117116
var proxiesFailed = false;
118-
StreamSubscription sigintSub;
119-
WebdevServer webdevServer;
117+
StreamSubscription? sigintSub;
118+
WebdevServer? webdevServer;
120119

121120
void shutDown(int code) async {
122121
await Future.wait([
123-
sigintSub?.cancel(),
124-
webdevServer?.close(),
122+
if (sigintSub != null) sigintSub.cancel(),
123+
if (webdevServer != null) webdevServer.close(),
125124
...proxies.map((proxy) => proxy.close()),
126125
]);
127126
if (!exitCodeCompleter.isCompleted) {
@@ -137,13 +136,13 @@ class ServeCommand extends Command<int> {
137136
});
138137

139138
// Parse the hostname to serve each dir on (defaults to 0.0.0.0)
140-
final hostnameResults = parseHostname(argResults.rest);
139+
final hostnameResults = parseHostname(argResults!.rest);
141140
final hostname = hostnameResults.hostname;
142141
final remainingArgs = hostnameResults.remainingArgs;
143142

144143
// Parse the directory:port mappings that will be used by the proxy servers.
145144
// Each proxy will be mapped to a `webdev serve` instance on another port.
146-
final portsToServeByDir = parseDirectoryArgs(argResults.rest);
145+
final portsToServeByDir = parseDirectoryArgs(argResults!.rest);
147146

148147
// Find open ports for each of the directories to be served by webdev.
149148
final portsToProxyByDir = {
@@ -173,8 +172,8 @@ class ServeCommand extends Command<int> {
173172
dir: dir,
174173
hostname: hostname,
175174
portToProxy: portsToProxyByDir[dir],
176-
portToServe: portsToServeByDir[dir],
177-
rewrite404s: argResults[rewrite404sFlag] == true,
175+
portToServe: portsToServeByDir[dir]!,
176+
rewrite404s: argResults![rewrite404sFlag] == true,
178177
));
179178
} catch (e, stackTrace) {
180179
proxiesFailed = true;

lib/src/sse_proxy_handler.dart

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,19 @@ String _sseHeaders(String origin) => 'HTTP/1.1 200 OK\r\n'
3434
/// simply forwards data back and forth between clients and the actual server.
3535
class SseProxyHandler {
3636
final _httpClient = http.Client();
37-
shelf.Handler _incomingMessageProxyHandler;
38-
final String _proxyName;
37+
late final shelf.Handler _incomingMessageProxyHandler =
38+
shelf_proxy.proxyHandler(
39+
_serverUri,
40+
client: _httpClient,
41+
proxyName: _proxyName,
42+
);
43+
final String? _proxyName;
3944
final Uri _proxyUri;
4045
final Uri _serverUri;
4146

4247
/// Creates an SSE proxy handler that will handle EventSource requests to
4348
/// [proxyUri] by proxying them to [serverUri].
44-
SseProxyHandler(Uri proxyUri, Uri serverUri, {String proxyName})
49+
SseProxyHandler(Uri proxyUri, Uri serverUri, {String? proxyName})
4550
: _proxyUri = proxyUri,
4651
_serverUri = serverUri,
4752
_proxyName = proxyName;
@@ -61,10 +66,10 @@ class SseProxyHandler {
6166

6267
req.hijack((channel) {
6368
final sink = utf8.encoder.startChunkedConversion(channel.sink)
64-
..add(_sseHeaders(req.headers['origin']));
69+
..add(_sseHeaders(req.headers['origin'] ?? ''));
6570

6671
StreamSubscription serverSseSub;
67-
StreamSubscription reqChannelSub;
72+
StreamSubscription? reqChannelSub;
6873

6974
serverSseSub =
7075
utf8.decoder.bind(serverResponse.stream).listen(sink.add, onDone: () {
@@ -75,7 +80,7 @@ class SseProxyHandler {
7580
reqChannelSub = channel.stream.listen((_) {
7681
// SSE is unidirectional.
7782
}, onDone: () {
78-
serverSseSub?.cancel();
83+
serverSseSub.cancel();
7984
sink.close();
8085
});
8186
});
@@ -100,11 +105,6 @@ class SseProxyHandler {
100105
}
101106

102107
Future<shelf.Response> _handleIncomingMessage(shelf.Request req) async {
103-
_incomingMessageProxyHandler ??= shelf_proxy.proxyHandler(
104-
_serverUri,
105-
client: _httpClient,
106-
proxyName: _proxyName,
107-
);
108108
return _incomingMessageProxyHandler(req);
109109
}
110110
}

lib/src/webdev_proc_utils.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ import 'package:pub_semver/pub_semver.dart';
2424
final webdevCompatibility = VersionConstraint.parse('>=1.0.1 <3.0.0');
2525

2626
@visibleForTesting
27-
ProcessResult cachedWebdevVersionResult;
27+
ProcessResult? cachedWebdevVersionResult;
2828

2929
/// Returns the version of the `webdev` package that is currently globally
3030
/// activated, or `null` if it is not activated.
31-
Version getGlobalWebdevVersion() {
31+
Version? getGlobalWebdevVersion() {
3232
cachedWebdevVersionResult ??= Process.runSync(
3333
'dart',
3434
['pub', 'global', 'run', 'webdev', '--version'],
3535
stdoutEncoding: utf8,
3636
);
37-
if (cachedWebdevVersionResult.exitCode != 0) {
37+
if (cachedWebdevVersionResult!.exitCode != 0) {
3838
return null;
3939
}
40-
return Version.parse(cachedWebdevVersionResult.stdout.toString().trim());
40+
return Version.parse(cachedWebdevVersionResult!.stdout.toString().trim());
4141
}
4242

4343
/// Prints the output from `webdev help serve` with a header that explains how

lib/src/webdev_proxy_server.dart

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import 'dart:io';
1616

1717
import 'package:http_multi_server/http_multi_server.dart';
1818
import 'package:io/ansi.dart';
19-
import 'package:meta/meta.dart';
2019
import 'package:shelf/shelf.dart' as shelf;
2120
import 'package:shelf/shelf_io.dart' as shelf_io;
2221
import 'package:shelf_proxy/shelf_proxy.dart' as shelf_proxy;
@@ -37,7 +36,7 @@ class WebdevProxyServer {
3736

3837
/// Permanently stops this proxy server from listening for new connections and
3938
/// closes all active connections immediately.
40-
Future<Null> close() async {
39+
Future<void> close() async {
4140
await _server.close(force: true);
4241
}
4342

@@ -51,15 +50,12 @@ class WebdevProxyServer {
5150
/// request that fetches the root index path (`/`) unless [rewrite404s] is
5251
/// false.
5352
static Future<WebdevProxyServer> start({
54-
@required String dir,
55-
@required String hostname,
56-
@required int portToProxy,
57-
int portToServe,
58-
bool rewrite404s,
53+
required String dir,
54+
required String hostname,
55+
required int? portToProxy,
56+
int portToServe = 0,
57+
bool rewrite404s = true,
5958
}) async {
60-
portToServe ??= 0;
61-
rewrite404s ??= true;
62-
6359
final serverHostname = hostname == 'any' ? 'localhost' : hostname;
6460
final serverUri = Uri.parse('http://$serverHostname:$portToProxy');
6561
final serverSseUri = serverUri.replace(path: r'/$sseHandler');
@@ -77,9 +73,8 @@ class WebdevProxyServer {
7773
final server = await HttpMultiServer.bind(hostname, portToServe);
7874
shelf_io.serveRequests(server, cascade.handler);
7975
final proxyHostname = hostname == 'any' ? '::' : hostname;
80-
log.info(green.wrap('Serving `$dir` proxy on '
81-
'http://$proxyHostname:$portToServe') +
82-
'\n');
76+
log.info(green
77+
.wrap('Serving `$dir` proxy on http://$proxyHostname:$portToServe\n'));
8378
log.fine('... forwards to http://$serverHostname:$portToProxy');
8479
return WebdevProxyServer._(server);
8580
}

lib/src/webdev_server.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,21 @@ class WebdevServer {
3030

3131
/// Permanently stops this proxy server from listening for new connections and
3232
/// closes all active connections immediately.
33-
Future<Null> close() async {
33+
Future<void> close() async {
3434
_process.kill();
3535
await _process.exitCode;
3636
}
3737

3838
/// Starts a `webdev serve` process with the given [args] and returns a
3939
/// [WebdevServer] abstraction over said process.
40-
static Future<WebdevServer> start(List<String> args) async {
40+
static Future<WebdevServer> start(List<String> args,
41+
{ProcessStartMode mode = ProcessStartMode.inheritStdio}) async {
4142
final webdevArgs = ['pub', 'global', 'run', 'webdev', 'serve', ...args];
4243
log.fine('Running `dart ${webdevArgs.join(' ')}');
4344
final process = await Process.start(
4445
'dart',
4546
webdevArgs,
46-
mode: ProcessStartMode.inheritStdio,
47+
mode: mode,
4748
);
4849
return WebdevServer._(process);
4950
}

0 commit comments

Comments
 (0)